动态构建的谓词未按预期工作
Dynamically built predicate is not working as expected
我的一个函数使用谓词定义查询在基于 EF 的数据库中搜索元素。它使用 param int[] paymentsIds
因为它可以使用可变数量的参数。所以我不得不动态地构造谓词。我有 2 个代码:一个静态代码(代码 2)和第二个 "almost dynamic with static parameters (code 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();
}
代码 1 的谓词打印到 Debug.Writeline:
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))
您不需要求助于复杂的谓词构建器,此查询归结为一个相当简单的查询:
return DbSet.Where(x => ids.Contains(x.Id) && x.UserData.Id == userId);
但是为了回答您的问题,您的代码中有一个小错字。带有 Where
子句的行使用 innerPredicate
而不是 outerPredicate
所以它应该是:
IQueryable<MwbePayment> query = DbSet.AsNoTracking().Where(outerPredicate);
我的一个函数使用谓词定义查询在基于 EF 的数据库中搜索元素。它使用 param int[] paymentsIds
因为它可以使用可变数量的参数。所以我不得不动态地构造谓词。我有 2 个代码:一个静态代码(代码 2)和第二个 "almost dynamic with static parameters (code 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();
}
代码 1 的谓词打印到 Debug.Writeline:
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))
您不需要求助于复杂的谓词构建器,此查询归结为一个相当简单的查询:
return DbSet.Where(x => ids.Contains(x.Id) && x.UserData.Id == userId);
但是为了回答您的问题,您的代码中有一个小错字。带有 Where
子句的行使用 innerPredicate
而不是 outerPredicate
所以它应该是:
IQueryable<MwbePayment> query = DbSet.AsNoTracking().Where(outerPredicate);