简体   繁体   English

使用EF6语法在EF Core中加载相关实体

[英]Eager loading related entities in EF Core using EF6 syntax

In EF6 we used to load related entities like this: 在EF6中,我们用来加载这样的相关实体:

query                                                   // (A)
  .Include(q => q.Employee.Supervisor.Office.Address)   
  .Include(q => q.Orders);

That would eager load all the entities in that chain. 那会急切加载该链中的所有实体。

In EF Core, you're supposed to do this: 在EF Core中,您应该这样做:

query                                                   // (B)
  .Include(q => q.Employee)
    .ThenInclude(q => q.Supervisor)
      .ThenInclude(q => q.Office)
        .ThenInclude(q => q.Address)
  .Include(q => q.Orders);

which is much (much!) less friendly, but works. 这很多(很多!)不太友好,但有效。

Our codebase has tons of (A) calls, which we must upgrade to (B) so we can use EF Core. 我们的代码库有大量的(A)调用,我们必须升级到(B)所以我们可以使用EF Core。

I've found that in many cases, EF Core works perfectly fine with (A) even though it shouldn't! 我发现在许多情况下,EF Core与(A)完全正常,即使它不应该! ...and sometimes it fails completely. ......有时它完全失败了。

Is that a fluke? 那是侥幸吗? Is it supposed to work with (A) under certain circumstances? 它是否应该在某些情况下与(A)一起使用? Because unless I have to, I don't feel like making many hundreds of changes, and then testing them. 因为除非我必须这样做,否则我不想进行数百次更改,然后对其进行测试。

Actually both syntaxes work in EF Core as far as the include path contains simple reference type (ie non collection type) navigation properties. 实际上,只要包含路径包含简单引用类型 (即非集合类型)导航属性,两种语法都在EF Core中工作。 It's because the "fluent" version of Include in both EF6 and EF Core is modeling a type safe way of describing a navigation property path like Root -> Employee -> Supervisor -> Office -> Address , which unsafe version is represented as string (also supported by both EF6 and EF Core) "Employee.Supervisor.Office.Address" . 这是因为EF6和EF Core中的Include的“流畅”版本正在建模一种类型安全的方式来描述导航属性路径,如Root - > Employee - > Supervisor - > Office - > Address ,其中不安全版本表示为string (也受EF6和EF Core支持) "Employee.Supervisor.Office.Address" EF Core examples seem to prefer always using the Include / ThenInclude pattern because it's more universal and works well for both reference and collection type properties as we will see later. EF Core示例似乎总是更喜欢使用Include / ThenInclude模式,因为它更通用,适用于引用和集合类型属性,我们将在后面看到。

The real difference comes when describing related properties of a collection type navigation properties. 描述集合类型导航属性的相关属性时会产生真正的差异。 Let assume the Order class from your example has a navigation property ICollction<OrderDetail> OrderDetails and OrderDetail class contains Vendor Vendor property. 假设您的示例中的Order类具有导航属性ICollction<OrderDetail> OrderDetailsOrderDetail类包含Vendor Vendor属性。 The string navigation path for including root + orders + order details + order detail vendors is "Orders.OrderDetails.Vendor" , but it cannot be simply represented as Include(q => q.Orders.OrderDetails.Vendor) expression (compile error). 包含root + orders +订单详细信息+订单明细供应商的string导航路径是"Orders.OrderDetails.Vendor" ,但它不能简单地表示为Include(q => q.Orders.OrderDetails.Vendor)表达式(编译错误) 。 Here the EF6 and EF Core take a different approach. EF6和EF Core采用不同的方法。 EF6 is resolving it using standard LINQ Select operator: EF6使用标准LINQ Select运算符解析它:

.Include(q => q.Orders.Select(o => o.OrderDetails.Select(d => d.Vendor)))

and EF Core - with ThenInclude custom extension method: 和EF Core - 使用ThenInclude自定义扩展方法:

.Include(q => q.Orders).ThenInclude(o => o.OrderDetails).ThenInclude(d => d.Vendor)

I can't say which one is better - both have a pros and cons. 我不能说哪一个更好 - 两者都有利有弊。 EF6 produces nesting, but allows external code to provide include expressions (of form Expression<Func<T, object>> ) without referencing the EF related assemblies. EF6生成嵌套,但允许外部代码提供包含表达式( Expression<Func<T, object>> )而不引用EF相关程序集。 From the other side EF Core syntax is "flat" and allows easy chaining additional properties w/o carrying if they are collection or reference, but there is no easy way to provide includes externally. 另一方面,EF Core语法是“平坦的”,如果它们是集合或引用,则允许轻松链接附加属性,但是没有简单的方法来提供外部包含。

But the main point is - better or not, the syntax for including a collection element related property is different and has to be considered when porting EF6 code to EF Core. 但重点是 - 无论是否更好,包含集合元素相关属性的语法是不同的,并且在将EF6代码移植到EF Core时必须考虑。 Actually in some initial EF Core versions the old syntax was supported (additionally to the new syntax), but for some unknown reason it has been removed. 实际上在一些初始EF Core版本中支持旧语法(除了新语法之外),但由于某些未知原因,它已被删除。 The only good thing is that you don't need to modify all your Include s - just find the ones using Select inside and convert them to ThenInclude syntax. 唯一的好处是你不需要修改所有Include - 只需找到使用Select inside的内容并将它们转换为ThenInclude语法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM