C# 在可选关系上强制从EF Cores Include()进行内部联接
我们将一个关系从required更改为optional,现在由EF-Core的Include()生成的SQL执行左外部连接而不是内部连接。问题是,这些可选实体上有必要的查询过滤器 假设我们有以下几点:C# 在可选关系上强制从EF Cores Include()进行内部联接,c#,asp.net-core,entity-framework-core,C#,Asp.net Core,Entity Framework Core,我们将一个关系从required更改为optional,现在由EF-Core的Include()生成的SQL执行左外部连接而不是内部连接。问题是,这些可选实体上有必要的查询过滤器 假设我们有以下几点: public class First { public int? SecondId { get; set; } } public class Second { public First First { get; set; } public int ThirdId { g
public class First
{
public int? SecondId { get; set; }
}
public class Second
{
public First First { get; set; }
public int ThirdId { get; set; }
}
public class Third
{
public Second Second { get; set; }
public string Tenant { get; set; }
}
public class MyContext : DbContext
{
protected readonly string _tenant;
...
modelBuilder.Entity<Third>(p =>
{
p.HasQueryFilter(x => Tenant == _tenant);
});
...
}
这将产生一个左外部联接,因为该关系是可选的。这当然会绕过查询过滤器。有没有办法让它包含一个内部连接
目前,可通过向以下位置添加更多条件来解决此问题:
.Where(p => p.Second.Third.Tenant == _tenant);
但这是不可取的,因为在某些边缘情况下_租户为null,然后会给出错误的数据
我知道我可以把它翻过来,然后继续
MyContext.Third.Include() ...
但这也是不可取的,因为在这个场景中,第一个有很多其他相关数据,我不想无休止地将Include()链接起来,然后将Include()链接到荒谬的地步
我可以强制使用可选实体进行内部连接吗?或者我必须为此手动编写SQL吗
我可以强制使用可选实体进行内部连接吗
你不能。你不应该。因为虽然内部连接
可能会解决您的特殊情况,但通常它会过滤所有具有null
FK(例如First.SecondId==null
)的依赖实体,这与可选关系的整个概念背道而驰
我看到的问题是,您似乎试图使用Include
进行过滤。按ideaInclude
就是它所说的-对于查询返回的每个实体,也包括相关数据。它不打算过滤实体或相关数据
因此,您需要的是一个查询过滤器
实际问题是EF核心不支持。这就是为什么在这种情况下,人们会打破规范化(引入冗余),将TenantId
属性(列)放在每个实体(表)中,这允许他们为每个实体设置全局过滤器
话虽如此,显式查询过滤器(其中
)是当前唯一的选项
但这是不可取的,因为在某些边缘情况下_租户为null,然后会给出错误的数据
例如,您只需要考虑可选关系的正确标准
.Where(p => p.SecondId == null || p.Second.Third.Tenant == _tenant);
但这实际上显示了每个实体上没有
租户的问题-当First.SecondId==null
时,您无法判断哪个租户拥有First
在这一行,其中(p=>p.Second.Third.Tenant==\u Tenant)代码>可以将其更改为。其中(p=>\u tenant!=null?\u tenant.Contain(p.Second.Third.tenant):p.Second.Third.tenant==p.Second.Third.tenant)代码>它能解决您的问题吗?因为我正在尝试“复制”一个内部联接,它不是:。其中(p=>p.SecondId!=null&&p.Second.Third.Tenant==\u Tenant)?谢谢你的详细回答。我猜这里最正确的做法是将租户添加到缺少租户的实体中。当然,如果您真的想模拟内部连接
,并过滤掉SecondId==null
的记录。
.Where(p => p.Second.Third.Tenant == _tenant);
.Where(p => p.SecondId == null || p.Second.Third.Tenant == _tenant);