【问题标题】:Dynamically built predicate is not working as expected动态构建的谓词未按预期工作
【发布时间】:2015-08-21 19:54:09
【问题描述】:

我的一个函数使用谓词定义查询来搜索基于 EF 的数据库中的元素。它使用param int[] paymentsIds,因为它可以使用可变数量的参数。所以我不得不动态地构造谓词。我有 2 个代码:一个是静态的(代码 2),第二个是“几乎是动态的,带有静态参数(代码 1)”。对我来说,它们都应该有效,但只有静态代码有效(代码 2)。为什么动态构造的谓词不起作用?

带有代码 1 和代码 2 开始和结束标记的方法代码:

public IEnumerable<MwbePayment> FindPaymentByIds(int userId, params int[] ids)
    {
        //code 1 starts
        ids = new int[] { 53, 54, 55 };
        //prepare predicate dynamically
        Expression<Func<MwbePayment, bool>> innerPredicate = PredicateBuilder.False<MwbePayment>();
        foreach (int id in ids)
        {
            int tempInt = id;
            innerPredicate = innerPredicate.Or(x => x.Id == tempInt);
        }

        Expression<Func<MwbePayment, bool>> outerPredicate = PredicateBuilder.And(innerPredicate, x => x.UserData.Id == userId);

        Debug.WriteLine("outerPredicate body = {0}", outerPredicate );
        IQueryable<MwbePayment> query = DbSet.AsNoTracking().Where(outerPredicate );

        //code 1 ends

        /*
        //code 2 starts
        Expression<Func<MwbePayment, bool>> innerPredicate2 = x => (x.Id == 53 || x.Id == 54 || x.Id == 55) && x.User.Id == userId;
        Debug.WriteLine("innerPredicate2 body = {0}", innerPredicate2);
        IQueryable<MwbePayment> query = DbSet.AsNoTracking().Where(innerPredicate2);
        //code 2 ends
        */

        return query.AsEnumerable();
    }

打印到 Debug.Writeline 的代码 1 的谓词:

f => (((False OrElse Invoke(x => (x.Id == value(MobileWallet.DAL.MwbePaymentRepository+<>c__DisplayClassc).tempInt), f)) OrElse Invoke(x => (x.Id == value(MobileWallet.DAL.MwbePaymentRepository+<>c__DisplayClassc).tempInt), f)) OrElse Invoke(x => (x.Id == value(MobileWallet.DAL.MwbePaymentRepository+<>c__DisplayClassc).tempInt), f))

代码 2 的谓词打印到 Debug.Writeline:

x => (((x.Id == 53) OrElse (x.Id == 54)) OrElse (x.Id == 55))

【问题讨论】:

    标签: c# entity-framework predicate


    【解决方案1】:

    您不需要求助于复杂的谓词构建器,这个查询归结为一个相当简单的查询:

    return DbSet.Where(x => ids.Contains(x.Id) && x.UserData.Id == userId);
    

    但是,要回答您的问题,您的代码中有一个小错字。带有Where 子句的行使用innerPredicate 而不是outerPredicate,所以它应该是:

    IQueryable<MwbePayment> query = DbSet.AsNoTracking().Where(outerPredicate);
    

    【讨论】:

    • 感谢您的回答,看起来不错,但仍然想知道我的想法有什么问题。
    • 那么第一个应该在Where 中使用outerPredicate 对吧?
    • 不需要带有 Userid.id 的条件,因为它导致两个谓词不相等。这是我的代码错误;)
    • 无论如何 :),我回滚了我的更新,以免在示例中出现混乱;)。感谢您的回答它有效:)
    猜你喜欢
    • 2020-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多