Когда использовать Include в EF? Не требуется в проекции?

entity-framework entity-framework-core

Вопрос

В Entity Framework Core есть следующее:

public class Book {
  public Int32 Id { get; set; }
  public String Title { get; set; }
  public virtual Theme Theme { get; set; }
}

public class Theme {
  public Int32 Id { get; set; }
  public String Name { get; set; }
  public Byte[] Illustration { get; set; }
  public virtual ICollection<Ebook> Ebooks { get; set; }
}

И у меня есть следующий запрос linq:

List<BookModel> books = await context.Books.Select(x =>
  new BookModel {
    Id = x.Id,
    Name = x.Name,
    Theme = new ThemeModel {
      Id = x.Theme.Id,
      Name = x.Theme.Name
    }
   }).ToListAsync();

Мне не нужно было включать тему для выполнения этой работы, например:

List<BookModel> books = await context.Books.Include(x => x.Theme).Select(x => ...

Когда мне нужно использовать Include в Entity Framework?

ОБНОВИТЬ

Я добавил столбец типа Byte [] Иллюстрация в теме. В моей проекции я не включаю этот столбец, поэтому он будет загружен, если я использую Include? Или никогда не загружается, если я не имею его в проекции?

Принятый ответ

Вам не нужно было включать Include, потому что вы работали внутри контекста EF. Когда вы ссылаетесь на Theme внутри анонимного объекта, который вы создаете, это не использует ленивую загрузку, что говорит EF о присоединении.

Если вы вернете список книг и не включаете темы, то при попытке получить тему вы заметите, что она равна нулю. Если соединение EF открыто и у вас есть ленивая загрузка, он перейдет к БД и возьмет его за вас. Но, если соединение не открывается, вы должны получить его явно.

С другой стороны, если вы используете Include, вы получаете данные сразу. Под капотом он собирается ПРИСОЕДИНИТЬСЯ к необходимой таблице и получать данные прямо там.

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


Популярные ответы

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

Если вы не Include или не ссылаетесь на ребенка каким-либо другим способом в запросе, исходный набор результатов меньше, но каждый дочерний элемент, который вы позже ссылаетесь, будет ленивым путем загрузки нового запроса в базу данных.

Если вы пропустите 1000 пользователей в одном запросе, а затем спросите их по 10 фотографий каждый, вы сделаете 1001 запросов к базе данных, если вы не Include его ...

Кроме того, ленивая загрузка требует, чтобы контекст не был удален. Всегда неприятный сюрприз, когда вы передаете Entity в представление для визуализации пользовательского интерфейса, например.

update Попробуйте это, например, и не получится:

var book = await context.Books.First();
var theme = book.Theme;

Затем попробуйте следующее:

var book = await context.Books.Include(b => b.Theme).First();
var theme = book.Theme;


Related

Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow