繁体   English   中英

实体框架包含左连接这可能吗?

[英]Entity Framework include with left join is this possible?

我有以下表格

  1. 教室 (ClassID,ClassName)
  2. StudentClass (StudentID,ClassID)
  3. 学生(学生 ID、学生姓名等)
  4. 学生说明。 (学生描述ID,学生ID,学生描述)

我要检索student==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;
    }

再次尝试不完整和错误

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 查询?

是的,有可能。

首先, .Include使用您通过的导航属性进行左外连接。

这是您在StudentStudentDescription之间显式执行 LEFT JOIN 的方式:

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

如您所见,它根据StudentsStudentDescriptions之间的实体关联执行 JOIN。 在您的 EF 模型中,您的Student实体上应该有一个名为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来完成。

我刚刚遇到了这个问题,就我而言,是 EntityTypeConfiguration 错误

我有:

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

代替:

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

似乎 HasRequired 进行了内部联接,而 HasOptional 进行了左联接。

确切地:

  1. 如果 StudentDescription.StudentId 可为空 -> EF 执行 LEFT JOIN,即select * from Student s LEFT JOIN StudentDescription sd on s.StudentID=sd.StudentID
  2. 否则 EF 执行 INNER JOIN。

如果您想要 1 对 1 的关系,您可以简单地映射您的外来 Id 并使其可以为空。

public int? MyForeignClassId { get; set; }
public MyForeignClass MyForeignClass { get; set; }

.Include的行为:

  • 要求属性:始终转换为INNER JOIN
  • 外键的类型不可为空:默认情况下转换为INNER JOIN ,但您可以添加.IsRequired(false).HasForeignKey以将其变为LEFT OUT JOIN
  • 属性类型是 collection 将始终转换为LEFT OUT JOIN

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM