Entity Framework с включенными / объединенными проблемами - PullRequest
1 голос
/ 14 декабря 2011

Я реализовал функцию наследования таблиц, продемонстрированную на 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());

1 Ответ

6 голосов
/ 14 декабря 2011

Очевидным решением для вас должно быть использование встроенной поддержки EF для наследования.В вашем случае наследование TPT .Получив наследство, вы просто позвоните:

IEnumerable<People> results = Entities.People
                                      .Where(x => x.Age == 25)
                                      .Take(100)
                                      .ToList();

И он вернет вам экземпляры Student, Teachers, Parents и т. Д.

В вашем решении единственный советэто проверить, что отношение необязательно (1 - 0..1) -.Если требуется, он будет использовать INNER JOIN.Если это необязательно и все еще использует INNER JOIN, это может быть ошибка или другая проблема в вашей модели.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...