right outer left inner framework c# entity-framework left-join

outer - linq left join c# entity framework



Entity Framework incluye con unir a la izquierda es esto posible? (3)

Tengo las siguientes tablas

  1. ClassRoom (ClassID, ClassName)
  2. StudentClass (StudentID, ClassID)
  3. Estudiante (StudentID, StudentName, Etc ..)
  4. Descripción del estudiante. (StudentDescriptionID, StudentID, StudentDescription)

Quiero recuperar toda la información sobre el estudiante == 1

En sql haría algo como ABAJO y obtendría toda la información sobre un estudiante.

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

Ahora mi problema. Usando EF4 hice algo como esto pero no puedo hacer que funcione. También puedes hacer un include y un join izquierdo

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

Intento 2 de nuevo incompleto e incorrecto

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

Como pueden ver, no sé qué estoy haciendo aquí. ¿Cómo puedo convertir ese SQL en una consulta EF?


Acabo de tener este problema, en mi caso fue la configuración de tipo de entidad que estaba mal.

Tuve:

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

En lugar de:

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

Parece que HasRequired hace un INNER JOIN mientras que HasOptional hace un IEFT JOIN.


Exactamente:

  1. Si StudentDescription.StudentId es anulable -> EF realiza un IZQUIERDA ÚNICA, es decir, select * from Student s LEFT JOIN StudentDescription sd on s.StudentID=sd.StudentID .
  2. De lo contrario, EF se une INNER.

Sí, es posible.

En primer lugar, .Include realiza una JUNTA EXTERNA IZQUIERDA, utilizando la propiedad de navegación que usted pasa.

Esta es la forma en que haría explícitamente una CONEXIÓN IZQUIERDA entre Student y StudentDescription :

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

Como puede ver, está realizando la UNIÓN basada en la asociación de entidades entre Students y StudentDescriptions . En su modelo EF, debe tener una propiedad de navegación llamada StudentDescriptions en su entidad de Student . El código anterior simplemente lo utiliza para realizar la unión y, de forma predeterminada, está vacío.

El código es básicamente idéntico a .Include .

Por favor, no se confunda con LEFT JOIN vs LEFT OUTER JOIN.

Ellos son la misma cosa.

La palabra clave "EXTERIOR" es opcional, creo que está ahí para compatibilidad ANSI-92.

Simplemente. .Include todo lo que necesita en su consulta:

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

Básicamente, asegúrese de que todos sus FK se expresen como propiedades de navegación en su modelo, entonces, de ser así, no necesita hacer ninguna unión. Cualquier relación que requiera se puede hacer con .Include .