Я реализовал функцию наследования таблиц, продемонстрированную на http://www.sqlteam.com/article/implementing-table-inheritance-in-sql-server.
Все внешние ключи и ограничения на месте.
Теперь я использую Entity Framework, чтобы оттянуть моих сотрудников, студентов, учителей и родителей, где модель выглядит примерно так (без всех специфических атрибутов 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 Query как:
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 **
Если я использую ответ Ладислава Мрнки , есть два дополнительных требования из-за значительных изменений в запросах Linq и Lambda.
Вопрос: Как мне искать конкретных людей с определенными свойствами?
(все учащиеся с оценкой «А»)
Ответ:
context.People.OfType<Student>().Where(s => s.Grade == "A");
Вопрос: Как мне искать людей с определенным свойством?
(Все учащиеся или учителя, у которых PrimaryFocus = "Math")
Ответ:
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());