[英]Eager Loading with LinqKit and EFCore
B"H B“高
C#sharps inclusion of linq right into the language is one of its most powerful features. C#将linq正确地包含在语言中是其最强大的功能之一。 It is also what makes Entity Framework such an enticing option for working with a database. 这也是使Entity Framework成为使用数据库的诱人选择的原因。
Unfortunately due to typing restrictions its often difficult to create centralized expressions to use throughout your project/solution. 不幸的是,由于类型限制,通常很难创建集中的表达式以在整个项目/解决方案中使用。
One answer to that question is LinqKit. 这个问题的一个答案是LinqKit。 This was working great for me in EF 6.x. 在EF 6.x中,这对我来说非常有效。 However when I moved to EF Core, I am facing a showstopper. 但是,当我移至EF Core时,我正面临着一场风头浪尖。
Instead of properly compiled expressions which should then be converted into SQL statement. 而不是正确编译的表达式,然后应将其转换为SQL语句。 What I am getting are function like expressions which don't include their sub expressions in the SQL that they generate. 我得到的是类似表达式的函数,它们在生成的SQL中不包含其子表达式。 Instead they create AsyncLinqOperatorProvider.EnumerableAdapter
s which .Net tries to execute (out of an async context) when you access the IEnumerables
a few lines later. 相反,它们创建AsyncLinqOperatorProvider.EnumerableAdapter
,当您稍后访问IEnumerables
时,.Net尝试执行(在异步上下文之外)。
So the question is: How do I get EF Core to execute the entire expression as one SQL statement and return a complete materialized object? 因此问题是:如何获得EF Core以一个SQL语句的形式执行整个表达式并返回一个完整的物化对象?
Given two classes 给定两个班
class OrderItemDTO
{
public string OrderItemName { get; set; }
}
class OrderDTO
{
public string OrderName { get; set; }
public ICollection<OrderItemDTO> OrderItems { get; set; }
}
I would like to create a global expressions somewhere 我想在某处创建全局表达式
public static Expression<Func<Order, OrderDTO>> ToDTO = x => new OrderDTO
{
OrderName = x.Name,
OrderItems = x.Items.Select(y => new OrderItemDTO { OrderItemName = y.Name })
};
Which I would then use somewhere as var orders = await db.Orders.AsExpandable().Select(ToDTO).ToListAsync();
然后我将在某处使用它作为var orders = await db.Orders.AsExpandable().Select(ToDTO).ToListAsync();
Expecting a fully materialized OrderDTO. 期待完全实现的OrderDTO。
Instead what I get is a DTO with OrderItems as a AsyncLinqOperatorProvider.EnumerableAdapter
which causes a race condition when executed 相反,我得到的是带有OrderItems的DTO作为AsyncLinqOperatorProvider.EnumerableAdapter
,这在执行时会导致竞争状况
Call AsQueryable()
and then ToList()
on your inner collections - EF will then be able to correctly treat this as full projection: 在内部集合上调用AsQueryable()
,然后调用ToList()
-EF将能够正确地将其视为完整投影:
public static Expression<Func<Order, OrderDTO>> ToDTO = x => new OrderDTO
{
OrderName = x.Name,
OrderItems = x.Items.AsQueryable().Select(y => new OrderItemDTO { OrderItemName = y.Name }).ToList()
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.