EF Core-我们可以使用EF.Functions.Like来动态处理OR运算符吗?

时间:2019-07-18 13:56:59

标签: c# entity-framework .net-core ef-core-2.2

我有一个简单的查询,其中WHERE子句看起来像这样:

where EF.Functions.Like(header.OrderNumber, numbers[0]) || EF.Functions.Like(header.CustomerPoNumber, numbers[0])

我特别使用EF.Functions.Like,因为我希望用户能够根据需要插入%。但是我正在努力弄清楚如何使它动态。从numbers[0]可以看出,我目前正在对第一个要测试的项目进行硬编码。但是实际上,我需要遍历这些项目,并在将它们添加到OR子句中时对它们进行WHERE

我以前用System.Linq.Dynamic.Core完成了此任务。我创建了一个动态WHERE语句,并使用了.Contains。但是问题在于.Contains在创建查询时强制使用双通配符。我需要让用户选择何时添加它。

关于如何实现此目标的任何想法?

1 个答案:

答案 0 :(得分:1)

您需要动态构建“ 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);