我可以在单个 Linq-to-SQL 语句中执行多个“.Contains”测试吗?

Can I do multiple ".Contains" tests in a single Linq-to-SQL statement?

我需要 return 所有匹配字符串列表之一的项目。用户输入以分号分隔的字符串列表:

abc; mno; xyz

我需要 return 产品代码(例如)包含 "abc" OR "mno" OR "xyz".

的所有项目

我有以下适用于一种情况的代码,正确 returning allItems 中的预期项目:

IQueryable<Items> allItems = FindItemsBasedOnSomeOtherCriteria();
var productCodes = inputString.Split(new char[] { ';', ',' }, StringSplitOptions.RemoveEmptyEntries);
IEnumerable<Item> results = null;

foreach (var productCode in productCodes)
{
    var query = allItems.Where(i => i.ProductCode.ToLower().Contains(productCode.ToLower()));

    if (results == null)
    {
        results = query;
    }
    else
    {
        results = results.Union(query);
    }
}

allItems = results.AsQueryable();

然而,在另一种情况下,我需要post-处理列表。这使用 allItems 作为另一个查询的输入之一。

当我在 inputString 中什么都没有或只有一个条目时,post 处理代码工作正常。但是,如果我有一个项目列表,我会引发以下异常:

An IQueryable that returns a self-referencing Constant expression is not supported.

导致问题的是 Union 语句。那么如何重写上面的循环使其不需要它呢?

理想情况下,我希望能够编写如下内容:

var productCodes = inputString.ToLower().Split(new char[] { ';', ',' }, StringSplitOptions.RemoveEmptyEntries);
var query = allItems.Where(i => productCodes.InverseContains(i.ProductCode.ToLower()));

但这不存在。

搜索抛出了这个问题:

Linq-to-SQL: Combining (OR'ing) multiple "Contains" filters?

问的是同样的问题,但接受的答案只是 link 到第 3rd 方工具包。

我已经尝试过其他构造,包括现在由 CodeCaster 建议的构造,但它们要么给出相同的错误,要么给出这个:

Local sequence cannot be used in LINQ to SQL implementations of query operators except the Contains operator.

供参考,代码为:

var result = allItems.Where(i => productCodes.Any(p => i.ProductCode.ToLower().Contains(p)));

不幸的是,这对于基本的 LINQ-to-SQL 是不可能的。另一个问题中已经接受的答案确实是正确的做法。

PredicateBuilder 和提到的 LINQKit 是开源的,可以在您的项目中简单地使用而不会出现任何问题。它也可以作为 NuGet package 使用,这使得您的项目中的使用更加简单。