无法翻译 LINQ 表达式。要么以可翻译的形式重写查询,要么切换到客户评估

问题描述 投票:0回答:3

我有 C# 应用程序 (.NET Core 3.1),并且我编写了以下 LINQ 表达式。

public ActionResult<bool> GetItems(string title)
{
     var items = _service.All.GetItems().OrderByDescending(o => o.Id).Where(w => w.Portal_Id == 1);

     if (!string.IsNullOrWhiteSpace(title))
     {
            var terms = title.Split(' ').ToList();
            items = items.Where(w => terms.Any(a => w.ItemName.Contains(a)));
     }
     // Some Other code
     return Ok();
}

每当执行此表达式时,我都会收到以下错误

The LINQ expression 'DbSet<PosItem>\r\n    .Where(p => !(p.IsDeleted))\r\n    
.OrderByDescending(p => p.CreatedAt)\r\n    .Where(p => p.Portal_Id == 1)\r\n    .Where(p => __terms_1\r\n      
.Any(a => p.ItemName.Contains(a)))' could not be translated.

Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by 
inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync().
See https://go.microsoft.com/fwlink/?linkid=2101038 for more information." 

我无法添加 ToList() 并切换到客户端评估,因为数据集太大,无法这样做。

请告知我如何在不切换到客户评估的情况下解决此问题。

谢谢

c# entity-framework linq .net-core
3个回答
31
投票

问题在于,您尝试在

string.Contains
表达式中执行
Any
,而 EF 会因尝试分解为 SQL 而窒息。 Ceptus 位于鼻子上,为
Where
子句构建谓词 OR-ing 术语比较。否则你的代码应该工作没有包含检查,而是平等检查:

没有

Contains
:(相等性检查而不是
LIKE %name%

var terms = title.Split(' ').ToList();
items = items.Where(w => terms.Contains(w.ItemName)); // IN clause.

内置表达式:

var terms = title.Split(' ').ToList();
Expression<Func<Item, bool>> predicate = (Item) => false;
foreach(var term in terms)
    predicate = predicate.Or(x => x.ItemName.Contains(term));

items = items.Where(predicate);

因此,对于标题中的每个术语,我们在 ItemName 上使用 LIKE %term% 进行 OR 匹配。


0
投票

在一个表达式中使用多个参数表达式时也会出现此问题。始终将 ParameterExpression 实例传输到所有 Expression.Property(argPara, "Name") 值。


0
投票

实际上我有不同的解决方案,这也适用于 sql、nosql (cosmos db) 我也有如下查询和错误, 为此,我尝试了很多,但除了浪费时间之外,没有任何效果正常...最终的简单解决方案是将 AsEnumerable() 添加到结果,如下所示,

© www.soinside.com 2019 - 2024. All rights reserved.