我有以下查询:
db.Users.AsQueryable()
.Where(u => u.Id = userResolver.LoggedUserId() && u.Packages.Where(p =>
p.StatusId == (int)PackageStatus.InProgress ||
p.StatusId == (int)PackageStatus.Delivered ||
p.StatusId == (int)PackageStatus.Shipped ||
p.StatusId == (int)PackageStatus.Waiting)
.Sum(p => p.Price) > u.MaxCredit)
.ToList()
我要实现的目标是将所有程序包状态检查归为一个扩展方法。像这样:
db.Users.AsQueryable()
.Where(u => u.Id = userResolver.LoggedUserId() &&
u.Packages.Where(p => p.IsShippedOrInProgress())
.Sum(p => p.Price) > u.MaxCredit)
.ToList()
//This is the extension method
public static bool IsShippedOrInProgress(this Package p) {
return p.StatusId == (int)PackageStatus.InProgress ||
p.StatusId == (int)PackageStatus.Delivered ||
p.StatusId == (int)PackageStatus.Shipped ||
p.StatusId == (int)PackageStatus.Waiting)
}
当我查看第一个示例中生成的sql查询时,一切似乎都不错,但是当我使用第二种方法时,检查状态的查询部分不存在。
答案 0 :(得分:3)
尝试使用此方法将创建Expression
,Package
作为输入和bool
作为输出:
public static System.Linq.Expressions.Expression<Func<Package, bool>> IsShippedOrInProgress()
{
return p => p.StatusId == ( int )PackageStatus.InProgress ||
p.StatusId == ( int )PackageStatus.Delivered ||
p.StatusId == ( int )PackageStatus.Shipped ||
p.StatusId == ( int )PackageStatus.Waiting);
}
这样称呼它:
private void SomeMethod()
{
db.Users.AsQueryable()
.Where(u => u.Id = userResolver.LoggedUserId() &&
u.Packages.Where(IsShippedOrInProgress())
.Sum(p => p.Price) > u.MaxCredit)
.ToList()
}
答案 1 :(得分:2)
我试图在记事本中写这个。因此可能存在错误。在评论中让我知道
public static Expression<Func<Package,bool>> IsShippedOrInProgress() {
// Compose the expression tree that represents the parameter to the predicate.
ParameterExpression p = Expression.Parameter(typeof(Package), "p");
// Compose left side of the expression i.e `p.StatusId`
Expression left = Expression.Call(p, typeof(Package).GetProperty("StatusId"));
// Compose right side of the expression i.e `(int)PackageStatus.InProgress` etc.
Expression exprInProgress = Expression.Constant((int)PackageStatus.InProgress);
Expression exprDelivered = Expression.Constant((int)PackageStatus.Delivered);
Expression exprShipped = Expression.Constant((int)PackageStatus.Shipped);
Expression exprWaiting = Expression.Constant((int)PackageStatus.Waiting);
// Compose left equals right side
Expression e1 = Expression.Equal(left, exprInProgress);
Expression e2 = Expression.Equal(left, exprDelivered);
Expression e3 = Expression.Equal(left, exprShipped);
Expression e4 = Expression.Equal(left, exprWaiting);
//Compose `p.StatusId == (int)PackageStatus.InProgress ||
// p.StatusId == (int)PackageStatus.Delivered ||
// p.StatusId == (int)PackageStatus.Shipped ||
// p.StatusId == (int)PackageStatus.Waiting`
Expression orConditions = Expressions.OrElse(Expression.OrElse(Expression.OrElse(e1,e2),e3),e4);
//Compose `p =>
// p.StatusId == (int)PackageStatus.InProgress ||
// p.StatusId == (int)PackageStatus.Delivered ||
// p.StatusId == (int)PackageStatus.Shipped ||
// p.StatusId == (int)PackageStatus.Waiting`
return Expression.Lambda<Func<Package, bool>>(orConditions, new ParameterExpression[] { p }));
}
更新
The C# compiler can generate expression trees from expression lambdas (or single-line lambdas)。请检查@Ankush答案