如何在实体框架中查询单个查询中的多个继承子类

本文关键字:查询 继承 子类 单个 实体 框架 | 更新日期: 2023-09-27 18:14:48

我在实体框架中的单个查询中查询不同类型的继承子实体时遇到了一个大问题。我的主要目标是通过即时加载在单个JSON字符串中提供所有数据模型结构。棘手的一点是"继承的子类可能包含另一个继承的子类"。下面的例子将清楚地解释这种情况。

假设我有一个像这样的简单类结构:

public class Teacher
    {
        public int id { get; set; }
        public string fullname{ get; set; }
        //navigation properties
        public virtual HashSet<Course> courses{ get; set; }
    }
public class Course
    {
        public int id { get; set; }
        public string coursename{ get; set; }
        //foreign keys
        public int TeacherId{ get; set; }
        //navigation properties
        public virtual Teacher teacher{ get; set; }
        public virtual HashSet<Course> prerequisites{ get; set; }
    }

Course有几个子类GradedCourse和UngradedCourseB1或B2可以有一个由B1或B2类型实体组成的子实体列表。

public class GradedCourse : Course
    {
        public string gradeType{ get; set; }
    }
public class UngradedCourse: Course
    {
        public string successMetric { get; set; }
    }

现在,通过这个结构,我想从我的WEBApi提供一个JSON结构,生成教师对象列表,包括GradedCourse和UngradedCourse及其子实体和特定字段。我有一个这样的查询,但它不编译

db.Teachers.Select(t => new 
  { 
  t.id,
  t.fullName
  courses = t.courses.OfType<GradedCourses>()
            .Select(g => new
              {
                id = g.id,
                coursename = g.coursename,
                prerequisites = g.prerequisites, // this is the list of other subentities 
                gradeType = g.gradeType 
              }
             ).Concat(t.courses.OfType<UngradedCourses>()
                       .Select(u => new
                         {
                          id = u.id,
                          coursename = u.coursename,
                          prerequisites = g.prerequisites, // this is the list of other subentities 
                          successMetric= u.successMetric // subclass specific field
                         }
                        )
               )
  } 
)

问题是连接两种不同类型的对象(它们有不同的字段,这对于SQL UNION是不可能的)

我该如何处理?任何帮助都会开阔我的眼界。提前感谢专业人士:)

如何在实体框架中查询单个查询中的多个继承子类

无法编译,因为两个集合的元素类型不相同。所以你只需要在做任何事情之前使它们相同:

db.Teachers.Select(t => new 
{ 
 t.id,
 t.fullName
 courses = t.courses.OfType<GradedCourses>()
            .Select(g => new
            {
              id = g.id,
              coursename = g.coursename,
              prerequisites = g.prerequisites, // this is the list of other subentities 
              isGradedCourse = true,
              gradeTypeOrMetric = g.gradeType 
            }).Concat(t.courses.OfType<UngradedCourses>()
              .Select(u => new
                     {
                      id = u.id,
                      coursename = u.coursename,
                      prerequisites = g.prerequisites, // this is the list of other subentities 
                      isGradedCourse = false,
                      gradeTypeOrMetric= u.successMetric // subclass specific field
                     }))
              //finally select what of your choice
              .Select(e => new {
                  id = e.id,
                  coursename = e.coursename,
                  prerequisites = e.prerequisites,
                  gradeType = e.isGradedCourse ? e.gradeTypeOrMetric : "",
                  successMetric = e.isGradedCourse ? "" : e.gradeTypeOrMetric
              })
});

您仍然受益于在服务器端执行查询,而不必将所有教师拉到本地(然后能够强制转换实体-这在LinqToEntity查询中不支持)。