EF Core присоединился сам? - PullRequest
2 голосов
/ 07 июня 2019

Я только что засвидетельствовал что-то странное

Давайте рассмотрим этот пример

publi class Order
{
    (...)
    public Status Status { get; set; }
    public Owner Owner { get; set; }
}

public class Status
{
    (...)
    public string Name { get; set; }
}

context
.Orders
.Include(x => x.Owner)
.Where(x => x.Owner.Id = 123)
.Where(x => x.Status.Name == "asdf")
.ToList();

Я был шокирован, когда этот код работал правильно - он нашел только те заказы с status name == asdf для Владельца с Id = 123 (he had orders of other type also), и я даже обнаружил, что Status является внутренним соединением

, но почему?Включить нет 1013

Возможно ли это, или мне придется попытаться найти ошибку в другом месте?

1 Ответ

3 голосов
/ 07 июня 2019

Include - это инструкция для eager-load связанных данных в том же операторе LINQ. Это не «объявление» свойств навигации, которые вы собираетесь использовать позже для фильтрации или выбора. Я часто вижу это замешательство. Подведем итоги:

Включить не обязательно для

  • Фильтрация данных

    context.Orders
           .Where(x => x.Owner.Id = 123)
           .Where(x => x.Status.Name == "In progress")
    

    ... генерирует SQL с двумя JOIN с и возвращает отфильтрованный Orders, без Owner или Status.

    context.Orders
           .Include(o => o.Owner)
           .Where(x => x.Owner.Id = 123)
           .Where(x => x.Status.Name == "In progress")
    

    ... возвращает отфильтрованный Orders с включенным только Owner.

  • Выбор данных

    context.Orders
           .Select(x => new
           { 
               x.Number,
               Owner = x.Owner.Name, 
               Status = x.Status.Name
           }
    

    ... снова генерирует SQL с двумя объединениями и возвращает объекты анонимного типа, без Owner, без Status.

    context.Orders
           .Include(o => o.Owner)
           .Select(x => new
           { 
               x.Number,
               Owner = x.Owner.Name, 
               Status = x.Status.Name
           }
    

    ... возвращает точно такие же данные, поскольку Include игнорируется . Если в конечном результате нет ничего, что могло бы содержать данные Include d, Include будет проигнорировано.

Обратите внимание, что Include оказывает влияние на запрос, такой как

context.Orders
       .Include(o => o.Owner)
       .Select(x => new
       { 
           Order = x,
           Owner = x.Owner.Name, 
           Status = x.Status.Name
       }

Несмотря на то, что возвращается анонимный тип, Order в нем является контейнером Owner и Owner. В EF 6 это было по-другому (и я полагаю, что в EF 6.3 на .NET Core 3.0 все еще было), там последнее Include также игнорировалось.

...