检查数据库列是否包含、以 EF 查询的 where 子句中的任何列表项开头或结尾不起作用



我试图从数据库中检索产品列表,其中名称包含,开始或结束于我作为参数传递给执行查询的方法的任何列表元素。

我已经尝试了Linq方法(方法和查询语法)

以下是Linq方法查询的相关代码,名称是作为方法参数传递的名称列表:

var query =  _dbContext.Products
.Where(p => p.IdExternalProduct == null && 
names.Any(name => p.ProductName.Contains(name)))
.Select(item => new ProductEntity() { Uuid = item.Uuid, Code = item.Code});

var query =  _dbContext.Products
.Where(p => p.IdExternalProduct == null && 
names.Any(name => p.ProductName.StartsWith(name)))
.Select(item => new ProductEntity() { Uuid = item.Uuid, Code = item.Code});

下面是查询语法方法:

IQueryable<ProductEntity> query = (
from p in _dbContext.Products
where 
p.IdExternalProduct == null &&
(names != null && names.Count > 0 ? names.Any(name => p.ProductName.Contains(name)) : true)
select new ProductEntity()
{
Uuid = p.Uuid,
Code = p.Code
}

当我尝试使用Equals而不是Contains,StartsWithEndsWith时,完全相同的查询工作。

我搜索了很多,找到了很多资源,但没有解决方案适合我。

这里有两个相关的Stack overflow问题,Jon Skeet建议使用相同的实现。

使用Linq

检查列表中的字符串是否包含特定的字符串正确的LINQ where子句

我正在使用6.0.10版本的实体框架和SQL Server提供程序。

但是这些公式似乎不能被翻译,抛出了一个异常,消息如下:

LINQ表达式的name =>EntityShaperExpression:
Service.Product。Products
ValueBufferExpression:
ProjectionBindingExpression: EmptyProjectionMember
IsNullable: False
. productname . contains (name)'无法翻译。要么以可翻译的形式重写查询,要么通过插入对'AsEnumerable', 'AsAsyncEnumerable', 'ToList'或'ToListAsync'的调用显式切换到客户端计算。详见https://go.microsoft.com/fwlink/?linkid=2101038

Jon Skeet在其他SO答案中推荐此实现的原因是因为它引用IEnumerable查询(linq-to-object)而不是IQueryable查询(linq-to-entities)。Linq-to-object在内存对象上执行,并且实际上将执行string.Contains方法。给EF的方法实际上并没有执行,它们被翻译成SQL语句,efcore 6不知道如何翻译你的语句,特别是name变量,它来自IEnumerable.Any调用中的linq到object lambda。

大多数开发人员忘记了IQueryable<T>是一个累积类型,您可以在其上聚合谓词。一个简单的解决方案是对每个名称进行联合查询,并区分所有结果:

var query = names.Select(name => _dbContext.Products
.Where(product => product.IdExternalProduct == null)
.Where(product => product.ProductName.Contains(name)))
.Aggregate(Queryable.Union)
.Distinct()
.Select(product => new ProductEntity(...));

这个查询产生以下语句:

DECLARE @__name_0 nvarchar(4000) = N'a';
DECLARE @__name_1 nvarchar(4000) = N'b';
SELECT DISTINCT [t].[Id], [t].[IdExternalProduct], [t].[ProductName]
FROM (
SELECT [p].[Id], [p].[IdExternalProduct], [p].[ProductName]
FROM [Products] AS [p]
WHERE ([p].[IdExternalProduct] IS NULL) AND ((@__name_0 LIKE N'') OR CHARINDEX(@__name_0, [p].[ProductName]) > 0)
UNION
SELECT [p0].[Id], [p0].[IdExternalProduct], [p0].[ProductName]
FROM [Products] AS [p0]
WHERE ([p0].[IdExternalProduct] IS NULL) AND ((@__name_1 LIKE N'') OR CHARINDEX(@__name_1, [p0].[ProductName]) > 0)
) AS [t]

相关内容

  • 没有找到相关文章

最新更新