Entity Framework include avec jointure à gauche est-ce possible?

c# entity-framework left-join

Question

J'ai les tables suivantes

  1. ClassRoom (ClassID, ClassName)
  2. StudentClass (StudentID, ClassID)
  3. Étudiant (StudentID, StudentName, Etc ..)
  4. StudentDescription. (StudentDescriptionID, StudentID, StudentDescription)

Je veux récupérer toutes les informations sur les étudiants == 1

Dans sql, je ferais quelque chose comme CI-DESSOUS et j'obtiendrais toutes les informations sur un étudiant.

 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

Maintenant mon problème. En utilisant EF4, j’ai fait quelque chose comme ça mais je ne peux pas le faire fonctionner. Aussi pouvez-vous faire une inclusion et une jointure à gauche

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

Tentative 2 à nouveau incomplète et erronée

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

Comme vous pouvez le constater, je ne sais pas ce que je fais ici. Comment puis-je convertir ce SQL en une requête EF?

Réponse acceptée

Oui c'est possible.

Premièrement, .Include effectue un LEFT OUTER JOIN, en utilisant la propriété de navigation que vous passez.

Voici comment vous feriez explicitement un LEFT JOIN entre Student et StudentDescription :

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

Comme vous pouvez le constater, l’opération JOIN est basée sur l’association d’entités entre Students et StudentDescriptions . Dans votre modèle EF, vous devez avoir une propriété de navigation appelée StudentDescriptions sur votre entité Student . Le code ci-dessus utilise simplement cela pour effectuer la jointure, et par défaut si vide.

Le code est fondamentalement identique à .Include .

S'il vous plaît ne vous trompez pas avec LEFT JOIN vs LEFT OUTER JOIN.

Ce sont les mêmes choses.

Le mot clé "OUTER" est facultatif. Je pense qu'il existe pour la compatibilité ANSI-92.

.Include tout ce dont vous avez besoin dans votre requête:

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

En gros, assurez-vous que tous vos FK sont exprimés en tant que propriétés de navigation sur votre modèle. Dans ce cas, vous n'avez pas besoin de faire de jointure. Toutes les relations dont vous avez besoin peuvent être réalisées avec .Include .


Réponse populaire

Je viens d'avoir ce problème, dans mon cas c'était la EntityTypeConfiguration qui était fausse

J'ai eu:

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

Au lieu de:

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

Il semble que HasRequired crée un INNER JOIN tandis que HasOptional crée un LEFT JOIN.



Related

Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow