【问题标题】:EFCore 3.1 - Exists query via Any; Query cannot be translatedEFCore 3.1 - 通过 Any 存在查询;无法翻译查询
【发布时间】:2020-05-22 09:08:19
【问题描述】:

我们正在使用 EFCore 3.1 并尝试使用 Exists 通过跨越 2 个属性的 .Any() 构建查询。

var selectionCriteria = someHugeList.Select(sh => new { sh.Id, sh.StatusCode }).ToList()
var resultsQry = _myContext.SomeClass
                           .Include(sc => sc.DetailRecords)
                           .Where(sc => selectionCriteria.Any(crit => crit.Id == sc.Id 
                                                                   && crit.StatusCode == sc.StatusCode));

var results = await resultsQry.ToListAsync()

在运行此查询时(即使有少量(5 项)选择条件项,它也会提供以下错误消息;

System.InvalidOperationException: LINQ 表达式 'DbSet .Where(c => __selectionCriteria_0 .Any(crit => crit.Id == sc.Id && crit.StatusCode == sc.StatusCode))' 无法翻译。 要么以可以翻译的形式重写查询,要么通过以下方式显式切换到客户端评估 插入对 AsEnumerable()、AsAsyncEnumerable()、ToList() 或 ToListAsync() 的调用。 请参阅https://go.microsoft.com/fwlink/?linkid=2101038 了解更多信息。'

似乎问题在于 .Any 子句中包含 2 个属性。 sql中存在的where通常可以毫无问题地做到这一点。 EFCore 似乎觉得这很困难。

有人知道如何解决这个问题吗?

【问题讨论】:

    标签: entity-framework linq exists any ef-core-3.1


    【解决方案1】:

    刚刚找到这个; https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-3.0/breaking-changes#linq-queries-are-no-longer-evaluated-on-the-client

    长话短说;客户端评估在 EFCore 3.1 中不再起作用,这意味着这种类型的查询(将客户端列表与服务器端列表进行比较)不起作用。你需要把它带给客户。我的同事刚才向我指出,我不欣赏错误消息的全部潜力:)。

    将我的查询更改如下(不是最佳的,但还没有其他解决方案):

    var selectionCriteria = someHugeList.Select(sh => new { sh.Id, sh.StatusCode }).ToList()
    var resultsQry = _myContext.SomeClass
                               .Include(sc => sc.DetailRecords)
                               .AsEnumerable() // this is the important part, pulling all the records client side so we can execute the .Any on the client.
                               .Where(sc => selectionCriteria.Any(crit => crit.Id == sc.Id 
                                                                       && crit.StatusCode == sc.StatusCode));
    
    var results = await resultsQry.ToList() // no more async, because clientside
    

    【讨论】:

    • 你能把.AsEnumerable() .Where(sc => selectionCriteria.Any(crit => crit.Id == sc.Id && crit.StatusCode == sc.StatusCode));改成..Where(sc => Ids.Contains(sc.Id) && Codes.Contains(sc.StatusCode))吗? Ids: 条件 id 列表,Codes: 状态代码列表并进行测试?
    • @MohammedSajid 的评论与解决方案 3 相同:在此 SO 中。它可能会导致过度采样,但最好关注链接并权衡取舍。
    猜你喜欢
    • 2021-04-13
    • 2021-12-07
    • 2021-06-23
    • 1970-01-01
    • 1970-01-01
    • 2021-05-28
    • 1970-01-01
    • 2020-12-29
    • 1970-01-01
    相关资源
    最近更新 更多