我已经实现了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; }
}
现在我需要让所有人不分类型,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();
看起来很简单,但无论我设置为包含哪个表/实体集,都会创建一个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]
为什么第一个包含用作INNER JOIN
,是否有解决方案?
**更新1 **
假设我使用了Ladislav Mrnka的Answer,由于Linq和Lambda查询的重大变化,还有两个额外的要求。
问题:如何搜索具有特定属性的特定人员?
(所有成绩为“A”的学生)
答案:
context.People.OfType<Student>().Where(s => s.Grade == "A");
问题:如何搜索具有特定属性的任何人?
(所有学生或教师的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());
答案 0 :(得分:6)
显而易见的解决方案应该是使用本机EF支持继承。在您的情况下TPT inheritance。继承后,您只需致电:
IEnumerable<People> results = Entities.People
.Where(x => x.Age == 25)
.Take(100)
.ToList();
它会返回Student
,Teachers
,Parents
等实例。
在您的解决方案中,唯一的建议是检查关系是否可选(1 - 0..1) - 。如果需要,它将使用INNER JOIN
。如果它是可选的并且它仍然使用INNER JOIN
,那么它可能是您模型中的一些错误或其他问题。