【问题标题】:EF Core - Can we do a dynamic number of OR operators with EF.Functions.Like?EF Core - 我们可以使用 EF.Functions.Like 执行动态数量的 OR 运算符吗?
【发布时间】:2019-11-27 11:48:49
【问题描述】:

我有一个简单的查询,其中 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 在创建查询时强制使用双通配符。我需要能够让用户选择何时包含它。

关于如何实现这一点的任何想法?

【问题讨论】:

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


    【解决方案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);
    

    【讨论】:

    • 非常感谢您的帮助。我正在尝试这个,但我遇到了 likeMethod 变量的问题。它抛出一个Ambiguous match found 错误。你会碰巧知道如何解决这个问题吗?与此同时,我正在努力。只是想看看你是否知道。
    • 我能够根据此 repo 中的代码修复它:github.com/aspnet/EntityFrameworkCore/issues/10834GetMethod(nameof(DbFunctionsExtensions.Like), new[] { typeof(DbFunctions), typeof(string), typeof(string) }); 再次感谢!这看起来很完美。
    • 很高兴您找到了解决方法。我在没有 EF 包的情况下工作,所以我只是看了一下 API 参考。我会用你的修复更新答案。
    猜你喜欢
    • 2012-09-25
    • 2012-04-20
    • 2023-03-15
    • 2020-09-23
    • 1970-01-01
    • 2012-10-15
    • 2015-05-22
    • 2021-09-11
    • 1970-01-01
    相关资源
    最近更新 更多