您可以使用我在以下位置找到并修改的扩展方法从列表中返回所有匹配项:Reference
这不是通用的,因此您必须将“ContainTest”更改为您的实体类型。
public static class EntityHelper
{
public static IQueryable<ContainTest> SqlLikeInList(this IQueryable<ContainTest> products, List<string> containsList)
{
if (!containsList.Any()) return null;
var patterns = containsList.Select(t => $"%{t}%").ToList();
ParameterExpression parameter = Expression.Parameter(typeof(ContainTest));
Expression body = patterns.Select(word => Expression.Call(typeof(DbFunctionsExtensions).GetMethod(nameof(DbFunctionsExtensions.Like),
new[]{typeof(DbFunctions), typeof(string), typeof(string)}),
Expression.Constant(EF.Functions),
Expression.Property(parameter, typeof(ContainTest).GetProperty(nameof(ContainTest.ProdYears))),
Expression.Constant(word)))
.Aggregate<MethodCallExpression, Expression>(null, (current, call) => current != null ? Expression.OrElse(current, call) : (Expression)call);
return products.Where(Expression.Lambda<Func<ContainTest, bool>>(body, parameter));
}
然后像这样从您的 DBSet 中调用它:
var years = new List<string> { "1390", "1391" };
IQueryable<ContainTest> queryable = context.ContainTests.SqlLikeInList(years);
通过测试,我发现如果您正在寻找“1390”或“1391”的完全匹配,所有这些都可以避免
years.Any(z => x.ProdYears == z)
...所以是 .contains 语句迫使您使用客户端评估。
但是,使用此扩展方法,您可以使用单个调用进行服务器端评估。
使用 SQL Server Profiler,我的示例生成了这个 SQL
SELECT [c].[ContainTestId], [c].[ProdYears], [c].[RequiredContentColumn]
FROM [ContainTests] AS [c]
WHERE ([c].[ProdYears] LIKE N'%1390%') OR ([c].[ProdYears] LIKE N'%1391%')
作为参考,我创建了一个实体来重新创建您的场景(这是 SQL 引用的内容)
public class ContainTest
{
public long ContainTestId { get; set; }
public string? ProdYears { get; set; }
public string RequiredContentColumn { get; set; }
}
我用这个示例数据填充了表格:
SET IDENTITY_INSERT [dbo].[ContainTests] ON
INSERT INTO [dbo].[ContainTests] ([ContainTestId], [ProdYears], [RequiredContentColumn]) VALUES (1, N'aa1389zz', N'dont get me')
INSERT INTO [dbo].[ContainTests] ([ContainTestId], [ProdYears], [RequiredContentColumn]) VALUES (2, N'zz1390aa', N'get me')
INSERT INTO [dbo].[ContainTests] ([ContainTestId], [ProdYears], [RequiredContentColumn]) VALUES (3, N'aa1391zz', N'get me too')
INSERT INTO [dbo].[ContainTests] ([ContainTestId], [ProdYears], [RequiredContentColumn]) VALUES (4, NULL, N'dont get me')
SET IDENTITY_INSERT [dbo].[ContainTests] OFF
编码愉快!!!