Почему левое внешнее соединение?

странный. (Наверное, не странно, вообще)

У меня есть 3 объекта, Employee, Rota и Department.

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 может быть назначен Сотрудник и/или Департамент, все это настроено с использованием Fluent. Все мои ассоциации верны (схема идеальна), однако у меня странная странность.

Когда я делаю myContext.Departments.FirstOrDefault() и смотрю на SQL Generated, на Employee и Rota есть LEFT OUTER JOIN. Почему это?
Я не хочу, чтобы это делалось. Может быть, мои ошибки Fluent неверны? Я пробовал все виды, но не могу понять. Я бы понял, хочу ли я объект Rota, который присоединился бы к Департаменту. Но не наоборот!

Если я делаю myContext.Departments.AsNoTracking().FirstOrDefault(), он не делает LEFT OUTER JOIN.

Любые идеи ребята?

Cheers, D

Ответ 1

Причина неправильного сопоставления. Это выглядит правильно, но это не так. Используйте их вместо:

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 не знает, существуют ли они, если они не загружают свои ключи.

Ответ 2

Я никоим образом не специалист, и я просто угадываю здесь. Но можете ли вы попытаться выполнить запрос, как это делает инфраструктура сущности, а затем попробовать его так, как вам хотелось бы видеть запрос и опубликовать временные дифференциалы. Возможно, инфраструктура сущности находится здесь, но я сомневаюсь.

Ответ 3

У меня есть теория. Левое внешнее соединение исчезает, когда вы отключите отслеживание изменений. Также сотрудники и Рота имеют ссылки на Департамент.

Итак, моя теория заключается в том, что отслеживание изменений в Entity Framework пытается загрузить все сущности со ссылкой на отдел в случае, если он должен каскадировать обновление для отдела.

Другими словами, он считает, что изменение в Департаменте может привести к изменению Employee или Rota, ссылающихся на отдел, чтобы он загружал все на всякий случай.