包含/加入问题的实体框架

Eri*_*ips 1 c# t-sql linq entity-framework-4

我已经实现了在http://www.sqlteam.com/article/implementing-table-inheritance-in-sql-server上演示的表继承功能.

所有外键和约束都已到位.

现在,我正在使用实体框架来撤回我的人员,学生,教师和家长,其中模型看起来类似于以下内容(没有所有EF特定属性等).

public partial class People : EntityObject
{
  public guid PeopleID { get; set; }
  public int Age { get; set; }  /Added for an example query
  public PeopleParent Parent { get; set; }
  public PeopleStudent Student { get; set; }
  public PeopleTeacher Teacher { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

现在我需要让所有人不分类型,25岁,不超过100条记录,并且我想要包含所有引用的数据.我创建我的EF查询,如:

IQueryable<People> query = Entities.People.Include("PeopleParent")
                                           .Include("PeopleStudent")
                                           .Include("PeopleTeacher");

query.Where(x => x.Age == 25)
     .Take(100);

IEnumerable<People> results = query.ToList();
Run Code Online (Sandbox Code Playgroud)

看起来很简单,但是我设置为包含的表/实体集首先创建一个INNER JOIN而不是生成一个LEFT OUTER JOIN,而不是产生正确的结果.

生成的TSQL(根据我的需要不正确):

SELECT 
  [Limit1].[C1] AS [C1],
  <A bunch of Limit1 Columns>
FROM (
  SELECT TOP (100) 
    [Extent1].[PeopleID] AS [PeopleID],
    <A bunch of Extent1 Columns>
    [Extent2].[PeopleID] AS [PeopleID1], 
    <A bunch of Extent2 Columns>
    [Extent3].[PeopleID] AS [PeopleID2], 
    <A bunch of Extent3 Columns>
    [Extent4].[PeopleID] AS [PeopleID3], 
    <A bunch of Extent4 Columns>
    1 AS [C1]
  FROM [rets].[People] AS [Extent1]
  INNER JOIN [rets].[PeopleParent] AS [Extent2] 
    ON [Extent1].[PeopleID] = [Extent2].[PeopleID]
  LEFT OUTER JOIN [rets].[PeopleStudent] AS [Extent3] 
    ON [Extent1].[PeopleID] = [Extent3].[PeopleID]
  LEFT OUTER JOIN [rets].[PeopleTeacher] AS [Extent4] 
    ON [Extent1].[PeopleID] = [Extent4].[PeopleID]
) AS [Limit1]
Run Code Online (Sandbox Code Playgroud)

为什么第一个包含被用作INNER JOIN,我的问题是否有解决方案?

**更新1**

假设我使用Ladislav Mrnka的答案,由于Linq和Lambda查询的重大变化,还有两个额外的要求.

问题:如何搜索具有特定属性的特定人员?

(所有成绩为"A"的学生)

回答:

context.People.OfType<Student>().Where(s => s.Grade == "A");
Run Code Online (Sandbox Code Playgroud)

问题:如何搜索具有特定属性的任何人?

(所有学生或教师的PrimaryFocus ="数学")

回答:

List<People> result = new List<People>();
result.AddRange(context.People.OfType<Student>()
                              .Where(x => x.PrimaryFocus == "Math")
                              .ToList());
result.AddRange(context.People.OfType<Teacher>()
                              .Where(x => x.PrimaryFocus == "Math")
                              .ToList());
Run Code Online (Sandbox Code Playgroud)

Lad*_*nka 6

显而易见的解决方案应该是使用本机EF支持继承.在你的情况下TPT继承.继承后,您只需致电:

IEnumerable<People> results = Entities.People
                                      .Where(x => x.Age == 25)
                                      .Take(100)
                                      .ToList();
Run Code Online (Sandbox Code Playgroud)

它将返回你的情况下Student,Teachers,Parents等.

在您的解决方案中,唯一的建议是检查关系是否可选(1 - 0..1) - .如果需要,它将使用INNER JOIN.如果它是可选的并且它仍然使用INNER JOIN它可能是您的模型中的一些错误或其他问题.