为什么左外部加入?

时间:2011-06-20 14:48:10

标签: c# sql entity-framework-4.1

奇怪的是。 (可能根本不奇怪)

我有3个对象,员工,罗塔和部门。

public class Employee
{
    public int Id { get; set; }
    public String Name { get; set; }
    public virtual Department Department { get; set; }
}

internal class EmployeeMapping : EntityTypeConfiguration<Employee>
{
    public EmployeeMapping()
    {
        HasKey(a => a.Id);
        Property(a => a.Id).HasColumnName("UserId");

        HasRequired<Department>(a => a.Department).WithOptional().Map(a => a.MapKey("DepartmentId"));
    }
}

public class Department
{
    public int Id { get; set; }
    public String Name { get; set; }
}

internal class DepartmentMapping : EntityTypeConfiguration<Department>
{
    public DepartmentMapping()
    {
        HasKey(a => a.Id);
        Property(a => a.Id).HasColumnName("DepartmentId");
    }
}

public class Rota
{
    public int Id { get; set; }
    public virtual Employee Employee { get; set; }
    public virtual Department Department { get; set; }
}

internal class RotaMapping : EntityTypeConfiguration<Rota>
{
    public RotaMapping()
    {
        HasKey(a => a.Id);
        Property(a => a.Id).HasColumnName("RotaId");

        HasOptional<Employee>(a => a.Employee).WithOptionalDependent().Map(a => a.MapKey("EmployeeId"));
        HasOptional<Department>(a => a.Department).WithOptionalDependent().Map(a => a.MapKey("DepartmentId"));
    }
}

一点也不复杂。 Rota可以为其分配一个Employee和/或Department,所有这些都是使用Fluent配置的。我的所有关联都是正确的(架构是完美的),但我有一个奇怪的怪异。

当我执行myContext.Departments.FirstOrDefault()并查看SQL Generated时,Employee&amp;上有一个 LEFT OUTER JOIN 。罗塔。这是为什么?我不希望它这样做。也许我的Fluent映射不正确?我已经尝试了各种各样的,但似乎无法弄明白。如果我想要一个可以加入部门的Rota对象,我会理解的。但不是相反!

如果我执行myContext.Departments.AsNoTracking().FirstOrDefault(),则不执行 LEFT OUTER JOIN

任何想法的人?

干杯, d

3 个答案:

答案 0 :(得分:5)

原因是映射不正确。看起来不错,但事实并非如此。请改用:

internal class EmployeeMapping : EntityTypeConfiguration<Employee>
{
    public EmployeeMapping()
    {
        HasKey(a => a.Id);
        Property(a => a.Id).HasColumnName("UserId");

        HasRequired<Department>(a => a.Department).WithMany()
                                                  .Map(a => a.MapKey("DepartmentId"));
    }
}

internal class RotaMapping : EntityTypeConfiguration<Rota>
{
    public RotaMapping()
    {
        HasKey(a => a.Id);
        Property(a => a.Id).HasColumnName("RotaId");

        HasOptional<Employee>(a => a.Employee).WithMany()
                                              .Map(a => a.MapKey("EmployeeId"));
        HasOptional<Department>(a => a.Department).WithMany()
                                                  .Map(a => a.MapKey("DepartmentId"));
    }
}

在创建数据库和数据库看起来正确时,您的映射被正确解释,但EF认为您将所有关系映射为一对一。这会混淆EF,它会生成用于一对一创建内部实体引用的查询。当您告诉EF依赖实体是可选的时,这些左连接对于一对一关系是必需的 - 除非加载其密钥,否则EF不知道它们是否存在。

答案 1 :(得分:0)

我绝不是专家,我只是在这里猜测。但是,您可以按照实体框架的方式尝试查询,然后以理想情况下查看查询并发布时间差异的方式进行尝试。也许实体框架在这里有所作为,但我对此表示怀疑。

答案 2 :(得分:0)

我有理论。关闭更改跟踪时,左外连接会消失。 Employee和Rota也提到了Department。

所以我的理论是,对于实体框架的更改跟踪尝试加载所有实体,并引用该部门,以防它必须将更新级联到部门。

换句话说,它认为对部门的更改可能会导致对Employee或Rota引用部门的更改,因此它会加载所有内容以防万一。