B“ H
C#sharps将linq包含在语言中是其最强大的功能之一。 这也是使Entity Framework成为使用数据库的诱人选择的原因。
不幸的是,由于键入限制,通常难以创建集中表达式以在整个项目/解决方案中使用。
该问题的一个答案是LinqKit。在EF 6.x中,这对我来说非常有效。 但是,当我迁移到EF Core时,我正面临着一场风头浪尖。
而不是正确编译的表达式,然后应将其转换为SQL语句。我得到的是类似表达式的函数,它们在生成的SQL中不包含其子表达式。相反,它们会创建AsyncLinqOperatorProvider.EnumerableAdapter
,当您稍后访问IEnumerables
时,.Net会尝试在异步上下文之外执行这些操作。
因此,问题是:如何获得EF Core作为一个SQL语句执行整个表达式并返回完整的物化对象?
给两个班
class OrderItemDTO
{
public string OrderItemName { get; set; }
}
class OrderDTO
{
public string OrderName { get; set; }
public ICollection<OrderItemDTO> OrderItems { get; set; }
}
我想在某个地方创建全局表达式
public static Expression<Func<Order, OrderDTO>> ToDTO = x => new OrderDTO
{
OrderName = x.Name,
OrderItems = x.Items.Select(y => new OrderItemDTO { OrderItemName = y.Name })
};
然后我将在哪个地方使用var orders = await db.Orders.AsExpandable().Select(ToDTO).ToListAsync();
期待完全实现的OrderDTO。
相反,我得到的是带有OrderItems作为AsyncLinqOperatorProvider.EnumerableAdapter
的DTO,它在执行时会导致竞争状态
答案 0 :(得分:0)
先调用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()
};