【问题标题】:How to rewrite EF LINQ query that used to work in .NET Core 2.0 but doesn't in 3.0?如何重写曾经在 .NET Core 2.0 中工作但在 3.0 中不起作用的 EF LINQ 查询?
【发布时间】:2020-06-02 18:14:20
【问题描述】:

我正在 .NET Core 3 中开发一个在线商店,遵循一些使用 .NET CORE 2 开发的教程。EF LINQ 在尝试执行这行简单的代码后出错:

var stocksToUpdate = _context.Stock
                             .Where(x => request.Stocks
                                                .Any(y => y.StockId == x.Id))
                             .ToList();   

我收到以下错误:

InvalidOperationException:无法翻译 LINQ 表达式“DbSet<Stock> .Where(s => __request_Stocks_0 .Any(y => y.StockId == s.Id))”。要么以可以翻译的形式重写查询, 或通过插入调用显式切换到客户端评估 AsEnumerable()、AsAsyncEnumerable()、ToList() 或 ToListAsync()。

老实说,我不知道如何以不同的方式编写该查询。我已尝试按照建议将 .ToList() 替换为 .AsEnumerable ,但它仍然出错,同样的错误。有谁知道 .NET Core 3 中的修复方法是什么? 提前致谢!

【问题讨论】:

    标签: c# linq asp.net-core-3.0 ef-core-3.0


    【解决方案1】:

    它在 EF Core 2.x 中“工作”,因为隐式客户端评估已在 3.0 中删除。您可以通过在报告的有问题的运算符之前插入AsEnumerable() before 来获得以前的行为 - 在您的情况下,Where

    var stocksToUpdate = _context.Stock
        .AsEnumerable()
        .Where(x => request.Stocks.Any(y => y.StockId == x.Id))
        .ToList();
    

    但删除隐式客户端评估的主要原因是效率低下 - 过滤发生在检索整个表后的内存中。

    因此,与其切换到客户评估,不如找到一个可翻译的结构。

    您的查询的问题是request.Stocks 是内存中的集合,EF Core 仅支持原始值的内存中集合,并且基本上支持Contains 方法。所以以下工作

    var stocksToUpdate = _context.Stock
        .Where(x => request.Stocks.Select(y => y.StockId).Contains(x.Id))
        .ToList();
    

    你也可以使用

    .Where(x => request.Stocks.Select(y => y.StockId).Any(y => y == x.Id))
    

    这里的基本部分是在使用ContainsAny 对其进行“调用”之前,将可枚举的内存中复杂对象转换为可枚举的单个原始值。

    【讨论】:

      猜你喜欢
      • 2020-01-25
      • 2020-03-29
      • 2020-08-20
      • 2022-01-26
      • 2012-08-12
      • 1970-01-01
      • 1970-01-01
      • 2021-12-16
      • 2020-10-28
      相关资源
      最近更新 更多