理解为什么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])中的列。
答案 0 :(得分:4)
[Extent2]
被使用 - 它是SQL的WHERE
的一部分。查询的结果将是正确的,但性能可能会更糟。我不认为SQL服务器会优化它以摆脱不必要的左连接。
这就是EF生成查询的方式。据我了解,EF不会跟踪实体集的使用情况,因此这两个查询部分Include(r => r.RotaGroup)
和Where(r => r.RotaGroup.IsCurrentRota)
彼此无关。左连接是Include
的结果,内连接是Where
的结果。您可以尝试修改查询,以便具有Include
的部分是过滤的子查询,但我怀疑它将以不同的方式工作。
答案 1 :(得分:1)
在我的结尾处遇到类似的问题,在不需要的情况下生成多个JOIN(即,可以很容易地将SQL查询更改为仅包含一个INNER JOIN到父表而不是同时具有INNER和LEFT JOIN到父表)。
我的问题还在于测试多个值的相等性(例如,child.ParentID == 1 || child.ParentID == 2 || child.ParentID == 3),这创建了一个搞乱的where子句(其中tbl1和tbl2是添加到SELECT语句的INNER和LEFT连接表:
WHERE tbl1.ParentID = 1或tbl2.ParentID IN(2,3)
这两个问题都已在2011年6月的CTP套餐中得到纠正: Entity framework CTP - June 2011