使用LinqKit和EFCore提前加载

时间:2019-07-16 15:04:05

标签: c# async-await entity-framework-core linqkit

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,它在执行时会导致竞争状态

1 个答案:

答案 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()
};