2010-11-27 3 views
22

Ich habe die folgenden TabellenEntity Framework Include mit Links Join ist das möglich?

  1. Classroom (ClassID, Classname)
  2. StudentClass (StudentID, ClassID)
  3. Student (StudentID, student, etc ..)
  4. StudentDescription. (StudentDescriptionID, StudentID, StudentDescription)

Ich möchte alle Informationen auf Schüler == abrufen 1

in SQL ich so etwas wie BELOW tun würde, und alle Informationen über einen Schüler bekommen.

Jetzt mein Problem. Unter Verwendung von EF4 habe ich so etwas getan, aber kann es nicht funktionieren. Auch können Sie eine Include und ein LEFT JOIN

Versuch 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; 
    } 

Versuch 2 wieder unvollständig und falsch

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(); 

Wie Sie sehen Ich weiß nicht, was ich hier tue. Wie kann ich diese SQL in eine EF-Abfrage konvertieren?

Antwort

27

Ja, es ist möglich.

Erstens, .Include macht eine LINKE OUTER JOIN, mit der Navigationseigenschaft Sie durchlaufen.

Dies ist, wie Sie explizit eine LEFT JOIN zwischen Studenten und StudentDescription tun würde:

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

Wie Sie sehen können, ist es die Durchführung der JOIN auf der Grundlage der Einheit Assoziation zwischen Students und StudentBeschreibungen. In Ihrem EF-Modell sollten Sie eine Navigationseigenschaft namens StudentDescriptions auf Ihrem Student Entität haben. Der obige Code verwendet einfach das, um den Join auszuführen, und den Standardwert, falls leer.

Der Code ist im Wesentlichen identisch mit .Include.

Bitte nicht mit LEFT JOIN vs LINKEN ÄUSSEREN VERBINDEN verwechseln.

Sie sind die gleiche Sache.

Das "OUTER" Schlüsselwort ist optional, ich glaube, es ist dort für ANSI-92-Kompatibilität.

Gerade .Include alles, was Sie in Ihrer Anfrage benötigen:

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(); 
     } 

Grundsätzlich stellen Sie sicher, alle Ihre FK ist als Navigationseigenschaften auf Ihrem Modell ausgedrückt werden, dann also, wenn Sie brauchen keine Verknüpfungen zu tun. Alle Beziehungen, die Sie benötigen, können mit .Include durchgeführt werden.

+1

danke für Ihre Zeit und antworten. Das Beispiel einbezieht funktioniert !! aber die erste erzeugt einen Kreuz-Join. Ich könnte total falsch sein, aber wenn du 2 Froms tust erzeugt das nicht einen Cross-Join? – user9969

+0

Ich habe diese Aussage nicht verstanden: "Erstens, .Include tut eine LINKE OUTER JOIN,". Soweit ich das beurteilen kann .Include führt einen INNEREN JOIN durch. – Dror

+0

Nein, '' .Include'' hat einen OUTER JOIN. Wenn Sie eine Eigenschaft einschließen, die zufällig leer ist (nicht vorhanden), wird die ursprüngliche zurückgegeben. –

7

Genau:

  1. Wenn StudentDescription.StudentId NULL-Werte zulässt -> EF führt eine LEFT JOIN, das heißt select * from Student s LEFT JOIN StudentDescription sd on s.StudentID=sd.StudentID.
  2. Ansonsten EF macht INNER JOIN.
15

Ich hatte gerade dieses Problem in meinem Fall war es die EntityTypeConfiguration die

Ich hatte nicht in Ordnung war:

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

Statt:

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

scheint es HasRequired Marken ein INNER JOIN während HasOptional einen LINKEN JOIN macht.