2010-11-27 2 views
22

나는 다음 표엔티티 프레임 워크가 왼쪽 조인을 포함 할 수 있습니까?

  1. 교실 (ClassID가, 클래스 이름)
  2. StudentClass (StudentID, ClassID가)
  3. 학생 (StudentID, StudentName, 기타 ..)
  4. StudentDescription 있습니다. (StudentDescriptionID, StudentID, StudentDescription)

은 내가 아래처럼 뭔가를하고 학생에 대한 모든 정보를 얻을 것이다 SQL에서 학생 == 1

의 모든 정보를 검색 할 수 있습니다.

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 쿼리로 변환하려면 어떻게해야합니까?

답변

27

예, 가능합니다.

먼저 .Include네비게이션 속성을 통과하여 LEFT OUTER JOIN을 수행합니다.

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

당신이, 그것은 학생사이의 엔티티 관계를 기반으로 JOIN 실적이 볼 수 있듯이 :

명시 적 StudentDescription 학생 사이 가입 왼쪽을 할 것 어떻게 StudentDescriptions. EF 모델에서 StudentDescriptions이라는 네비게이션 속성이 학생 엔티티에 있어야합니다. 위의 코드는 단순히 그것을 사용하여 조인을 수행하고 비어있는 경우 기본값으로 설정합니다.

코드는 기본적으로 .Include과 동일합니다.

LEFT JOINLEFT 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으로 할 수 있습니다.

+1

시간과 답례에 감사드립니다. 예제가 포함됩니다! 그러나 첫 번째 교차 결합을 생산하고 있습니다. 나는 완전히 틀릴 수도 있지만 당신이 그것을 할 때 그것은 교차 결합을 생산하지 않습니다? – user9969

+0

나는이 진술을 이해하지 못했다 : "첫째,. 포함하는 것은 LEFT OUTER JOIN을 포함한다". 내가 말할 수있는 한, INCLUDE는 INNER JOIN을 수행한다. – Dror

+0

아니요,''.Include''는 OUTER JOIN을합니다. 비어있는 (존재하지 않는) 속성을 포함 시키면 원래의 속성은 여전히 ​​반환됩니다. –

7

정확히 : StudentDescription.StudentId가 널이면

  1. 는 -> EF, 즉 select * from Student s LEFT JOIN StudentDescription sd on s.StudentID=sd.StudentID 좌측 조인 행한다.
  2. 그렇지 않으면 EF가 INNER JOIN을 수행합니다.

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

    대신에 :

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

    그것은 HasRequired 보인다 차종

15

난 그냥, 내 경우는

내가 가진 잘못했다 EntityTypeConfiguration이 문제였다했다 HasOptional가 LEFT JOIN을하는 동안 INNER JOIN.

관련 문제