EF Core - 我们可以使用 EF.Functions.Like 执行动态数量的 OR 运算符吗?
EF Core - Can we do a dynamic number of OR operators with EF.Functions.Like?
我有一个简单的查询,其中 WHERE 子句如下所示:
where EF.Functions.Like(header.OrderNumber, numbers[0]) || EF.Functions.Like(header.CustomerPoNumber, numbers[0])
我专门使用 EF.Functions.Like
,因为我希望用户能够根据需要插入 %
。但是我正在努力弄清楚如何使它充满活力。正如您从 numbers[0]
中看到的那样,我目前正在对要测试的第一项进行硬编码。但实际上,我需要遍历这些项目并在将它们添加到 WHERE
子句时对每个项目执行 OR
。
我以前用 System.Linq.Dynamic.Core
完成过这个。我创建了一个动态 WHERE
语句并使用 .Contains
。但问题是 .Contains
在创建查询时强制使用双通配符。我需要能够让用户选择何时包含它。
关于如何实现这个的任何想法?
您需要动态构建 "where" 谓词。
可以使用 Expressions
:
// We want to build dynamically something like:
// x => EF.Functions.Like(x.OrderNumber, v1) || EF.Functions.Like(x.OrderNumber, v2)...
var likeMethod = typeof(DbFunctionsExtensions).GetMethod(nameof(DbFunctionsExtensions.Like), new[] { typeof(DbFunctions), typeof(string), typeof(string) });
var entityProperty = typeof(Header).GetProperty(nameof(Header.OrderNumber), BindingFlags.Instance | BindingFlags.Public);
// EF.Functions.Like(x.OrderNumber, v1) || EF.Functions.Like(x.OrderNumber, v2)...
Expression likePredicate = null;
var efFunctionsInstance = Expression.Constant(EF.Functions);
// Will be the predicate paramter (the 'x' in x => EF.Functions.Like(x.OrderNumber, v1)...)
var lambdaParam = Expression.Parameter(typeof(Header));
foreach (var number in numbers)
{
// EF.Functions.Like(x.OrderNumber, v1)
// |__|
var numberValue = Expression.Constant(number);
// EF.Functions.Like(x.OrderNumber, v1)
// |_____________|
var propertyAccess = Expression.Property(lambdaParam, entityProperty);
// EF.Functions.Like(x.OrderNumber, v1)
//|____________________________________|
var likeMethodCall = Expression.Call(likeMethod, efFunctionsInstance, propertyAccess, numberValue);
// Aggregating the current predicate with "OR" (||)
likePredicate = likePredicate == null
? (Expression)likeMethodCall
: Expression.OrElse(likePredicate, likeMethodCall);
}
// x => EF.Functions.Like(x.OrderNumber, v1) || EF.Functions.Like(x.OrderNumber, v2)...
var lambdaPredicate = Expression.Lambda<Func<Header, bool>>(likePredicate, lambdaParam);
var filteredQuery = query.Where(lambdaPredicate);
我有一个简单的查询,其中 WHERE 子句如下所示:
where EF.Functions.Like(header.OrderNumber, numbers[0]) || EF.Functions.Like(header.CustomerPoNumber, numbers[0])
我专门使用 EF.Functions.Like
,因为我希望用户能够根据需要插入 %
。但是我正在努力弄清楚如何使它充满活力。正如您从 numbers[0]
中看到的那样,我目前正在对要测试的第一项进行硬编码。但实际上,我需要遍历这些项目并在将它们添加到 WHERE
子句时对每个项目执行 OR
。
我以前用 System.Linq.Dynamic.Core
完成过这个。我创建了一个动态 WHERE
语句并使用 .Contains
。但问题是 .Contains
在创建查询时强制使用双通配符。我需要能够让用户选择何时包含它。
关于如何实现这个的任何想法?
您需要动态构建 "where" 谓词。
可以使用 Expressions
:
// We want to build dynamically something like:
// x => EF.Functions.Like(x.OrderNumber, v1) || EF.Functions.Like(x.OrderNumber, v2)...
var likeMethod = typeof(DbFunctionsExtensions).GetMethod(nameof(DbFunctionsExtensions.Like), new[] { typeof(DbFunctions), typeof(string), typeof(string) });
var entityProperty = typeof(Header).GetProperty(nameof(Header.OrderNumber), BindingFlags.Instance | BindingFlags.Public);
// EF.Functions.Like(x.OrderNumber, v1) || EF.Functions.Like(x.OrderNumber, v2)...
Expression likePredicate = null;
var efFunctionsInstance = Expression.Constant(EF.Functions);
// Will be the predicate paramter (the 'x' in x => EF.Functions.Like(x.OrderNumber, v1)...)
var lambdaParam = Expression.Parameter(typeof(Header));
foreach (var number in numbers)
{
// EF.Functions.Like(x.OrderNumber, v1)
// |__|
var numberValue = Expression.Constant(number);
// EF.Functions.Like(x.OrderNumber, v1)
// |_____________|
var propertyAccess = Expression.Property(lambdaParam, entityProperty);
// EF.Functions.Like(x.OrderNumber, v1)
//|____________________________________|
var likeMethodCall = Expression.Call(likeMethod, efFunctionsInstance, propertyAccess, numberValue);
// Aggregating the current predicate with "OR" (||)
likePredicate = likePredicate == null
? (Expression)likeMethodCall
: Expression.OrElse(likePredicate, likeMethodCall);
}
// x => EF.Functions.Like(x.OrderNumber, v1) || EF.Functions.Like(x.OrderNumber, v2)...
var lambdaPredicate = Expression.Lambda<Func<Header, bool>>(likePredicate, lambdaParam);
var filteredQuery = query.Where(lambdaPredicate);