何时使用包含在 EF 中?投影中不需要吗?

问题描述 投票:0回答:3

我在 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 in Entity Framework?

更新

我在主题中添加了一列 Byte[] Illustration 类型的列。在我的投影中,我没有包含该列,因此如果我使用“包含”,它会被加载吗?或者永远不会加载,除非我把它放在投影中?

entity-framework entity-framework-core
3个回答
10
投票

在从 Microsoft 方面寻找您的问题的官方答案时,我发现了 Diego Vega(实体框架和 .NET 团队的一部分)的这句话 在 aspnet/Announcements github 上发表 存储库

在查看用户 LINQ 查询时,我们看到的一个非常常见的问题是使用 Include(),这是不必要的,也不能被尊重。典型的模式通常看起来像这样:

var pids = context.Orders
    .Include(o => o.Product)
    .Where(o => o.Product.Name == "Baked Beans")
    .Select(o =>o.ProductId)
    .ToList();

人们可能会认为此处的 Include 操作是必需的,因为在Where 和Select 操作中引用了Product 导航属性。然而,在 EF Core 中,这两件事是正交的:包括在最终结果返回的实体中加载导航属性的控件,并且我们的 LINQ 翻译器可以直接翻译涉及导航属性的表达式。


9
投票

您不需要 Include,因为您是在 EF 上下文中工作。当您在创建的匿名对象中引用 Theme 时,这不是使用延迟加载,而是告诉 EF 进行联接。

如果您返回书籍列表并且不包含主题,那么当您尝试获取主题时,您会发现它是空的。如果 EF 连接打开并且您有延迟加载,它将转到数据库并为您抓取它。但是,如果连接未打开,那么您必须显式获取它。

另一方面,如果您使用 Include,您会立即获得数据。在幕后,它将执行 JOIN 到必要的表并在那里获取数据。

您可以检查 EF 为您生成的 SQL 查询,这会让您更清楚。您只会看到一个 SQL 查询。


5
投票

如果您

Include
是一个子项,它会作为原始查询的一部分加载,这会使其更大。

如果您不

Include
或在查询中以其他方式引用子项,则初始结果集会较小,但您稍后引用的每个子项将通过对数据库的新请求进行延迟加载。

如果您在一个请求中循环访问 1000 个用户,然后分别询问他们的 10 张照片,那么如果您不这样做,您将发出 1001 个数据库请求

Include
孩子...

此外,延迟加载要求上下文尚未被释放。例如,当您将实体传递给视图以进行 UI 渲染时,总是会出现令人不快的意外。

更新 尝试一下这个例子,看看它失败了:

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

那就试试这个:

var book = await context.Books.Include(b => b.Theme).First();
var theme = book.Theme;
© www.soinside.com 2019 - 2024. All rights reserved.