Подтвердить что ты не робот

Entity Framework включает в себя левое соединение, возможно ли это?

У меня есть следующие таблицы

  • ClassRoom (ClassID, ClassName)
  • StudentClass (StudentID, ClassID)
  • Студент (StudentID, StudentName, Etc..)
  • StudentDescription. (StudentDescriptionID, StudentID, StudentDescription)

Я хочу получить всю информацию об ученике == 1

В sql я бы сделал что-то вроде НИЖЕ и получал всю информацию о студенте.

 select * from Student s
 join StudentClass sc on s.StudentID=sc.StudentID
 join ClassRoom c on sc.ClassID=c.ClassID
 left join StudentDescription sd on s.StudentID=sd.StudentID
 where s.StudentID=14

Теперь моя проблема. Использование EF4 Я сделал что-то вроде этого, но не могу заставить его работать. Также вы можете сделать включение и левое соединение

Попытка 1

private static StudentDto LoadStudent(int studentId)
    {
        StudentDto studentDto = null;
        using (var ctx = new TrainingContext())
        {
            var query = ctx.Students
                .Include("ClassRooms")
                .Include("StudentDescriptions")
                .Where(x=>x.StudentID==studentId)
                .SingleOrDefault();

            studentDto = new StudentDto();
            studentDto.StudentId = query.StudentID;
            studentDto.StudentName = query.StudentName;
            studentDto.StudentDescription = ??

        }

        return studentDto;
    }

Попытка 2 снова неполная и неправильная

using (var ctx = new TrainingContext())
         {
             var query = (from s in ctx.Students
                             .Include("ClassRooms")
                         join sd in ctx.StudentDescriptions on s.StudentID equals sd.StudentID into g
                         from stuDesc in g.DefaultIfEmpty()
                         select new
                                    {
                                        Name=s.StudentName,
                                        StudentId=s.StudentID,

         }).SingleOrDefault();

Как вы можете видеть, я не знаю, что я здесь делаю. Как я могу преобразовать этот Sql в запрос EF?

4b9b3361

Ответ 1

Да, это возможно.

Во-первых, .Include выполняет LEFT OUTER JOIN, используя навигационное свойство, которое вы проходите.

Вот как вы бы явно делали LEFT JOIN между Student и StudentDescription:

var query = from s in ctx.Students
            from sd in s.StudentDescriptions.DefaultIfEmpty()
            select new { StudentName = s.Name, StudentDescription = sd.Description };

Как вы можете видеть, он выполняет JOIN на основе ассоциации сущностей между Student и StudentDescriptions. В вашей модели EF у вас должно быть навигационное свойство StudentDescriptions на вашей Студент. Вышеприведенный код просто использует это для выполнения соединения и по умолчанию считается пустым.

Код в основном идентичен .Include.

Не путайте с LEFT JOIN vs LEFT OUTER JOIN.

Это одно и то же.

Ключевое слово "OUTER" является необязательным, я считаю, что он совместим с ANSI-92.

Просто .Include все, что вам нужно в вашем запросе:

using (var ctx = new TrainingContext())
        {
            studentDo = ctx.Students
                .Include("ClassRooms")
                .Include("StudentDescriptions")
                .Where(x=>x.StudentID==studentId)
                .Select(x => new StudentDto
                        {
                            StudentId = x.StudentId,
                            StudentName = x.StudentName
                            StudentDescription = x.StudentDescription.Description
                        })
                .SingleOrDefault();
        }

В принципе, убедитесь, что все ваши FK выражены как навигационные свойства на вашей модели, а если это так, вам не нужно делать никаких соединений. Любые необходимые вам отношения можно выполнить с помощью .Include.

Ответ 2

У меня была эта проблема, в моем случае это была ошибка EntityTypeConfiguration

У меня было:

   HasRequired(s => s.ClassRoom)
                .WithMany()
                .HasForeignKey(student => student.ClassRoomId);

Вместо:

   HasOptional(s => s.ClassRoom)
                .WithMany()
                .HasForeignKey(student => student.ClassRoomId);

Кажется, HasRequired делает INNER JOIN, а HasOptional делает LEFT JOIN.

Ответ 3

именно:

  • Если StudentDescription.StudentId имеет значение NULL → EF выполняет LEFT JOIN, т.е. select * from Student s LEFT JOIN StudentDescription sd on s.StudentID=sd.StudentID.
  • В противном случае EF делает INNER JOIN.