实体框架生成的SQL问题(同一表上有多个联接)
本文关键字:框架 SQL 问题 实体 | 更新日期: 2023-09-27 18:00:50
理解EF(4.1(生成特定SQL查询的原因有点问题。如下:
基本上我有这两类
public class Rota
{
public int RotaId { get; set; }
public int RotaGroupId { get; set; }
public virtual RotaGroup RotaGroup { get; set; }
public int EmployeeId { get; set; }
public virtual Employee Employee { get; set; }
...
和
public class RotaGroup
{
public int RotaGroupId { get; private set; }
public bool IsCurrentRota { get; set; }
...
rota的映射如下:
HasKey(r => r.RotaId);
Property(r=>r.RotaId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
HasRequired(r => r.RotaGroup).WithMany()
.HasForeignKey(r => r.RotaGroupId)
.WillCascadeOnDelete(false);
HasRequired(r => r.Employee).WithMany()
.HasForeignKey(r => r.EmployeeId)
.WillCascadeOnDelete(false);
好的。现在下面的linq查询:
_context.Rotas.Include(r => r.RotaGroup)
.Where(r => r.EmployeeId == 1 && r.RotaGroup.IsCurrentRota)
.ToList();
生成以下SQL:
SELECT ...columns...
FROM [dbo].[Rota] AS [Extent1]
INNER JOIN [dbo].[RotaGroup] AS [Extent2] ON [Extent1].[RotaGroupId] = [Extent2][RotaGroupId]
LEFT OUTER JOIN [dbo].[RotaGroup] AS [Extent3] ON [Extent1].[RotaGroupId] = [Extent3].[RotaGroupId]
WHERE ([Extent2].[IsCurrentRota] = 1) AND ([Extent1].[MyIgluUserId] = 1
我相信你能看到这个问题。为什么,哦,为什么它加入了rotaGroup(应该加入(,然后进行左外加入?此外,不使用[Extent2](内部联接(中的列。仅使用来自左侧外部联接位([Extent3](的列。
[Extent2]
被使用-它是SQL的WHERE
的一部分。查询的结果将是正确的,但性能可能会更差。我不认为SQL server会对此进行优化以消除不必要的左联接。
EF就是这样生成查询的。据我所知,EF不跟踪实体集的使用,所以这两个查询部分Include(r => r.RotaGroup)
和Where(r => r.RotaGroup.IsCurrentRota)
彼此不相关。左联接是Include
的结果,内联接是Where
的结果。您可以尝试修改查询,使Include
的部分是过滤的子查询,但我怀疑它的工作方式会有所不同。
我遇到了一个类似的问题,即当不需要多个JOIN时会生成多个JOINN(即,SQL查询可以很容易地更改为只包含一个父表的INNER JOIN,而不是同时包含一个INNER和LEFT JOIN(。
我的问题还涉及测试多个值的相等性(例如,where child.ParentID==1||child.Parent ID=2=|child.PParentID==3(,这创建了一个混乱的where子句(其中tbl1和tbl2是添加到SELECT语句中的INNER和LEFT联接表(:
其中tbl1.ParentID=1或tbl2.ParentID在(2,3(中
这两个问题都已在2011年6月的CTP包中得到纠正:实体框架CTP-2011年6月