结合两个表达式

时间:2011-05-02 09:54:04

标签: c# .net entity-framework linq-to-entities

我正在尝试创建一个在实体框架查询中使用的表达式。 我创建了两个表达式:

public Expression<Func<IEntityPriceDefinition, bool>> IsMatchExpression(long additionId)
    {
        return x => x.PriceDefinition.AdditionsPrices.Any(a => a.AdditionId == additionId);
    }
public Expression<Func<IEntityPriceDefinition, bool>> IsMatchExpression(
    long? inviterId, long? routeId, long? luggageTypeId)
{
    return x =>
        (inviterId.HasValue || routeId.HasValue || luggageTypeId.HasValue) &&
        !(
            (x.PriceDefinition.InviterId.HasValue && inviterId.HasValue &&
                PriceDefinition.InviterId.Value != inviterId.Value) ||

            (PriceDefinition.LuggageTypeId.HasValue && luggageTypeId.HasValue &&
                PriceDefinition.LuggageTypeId.Value != luggageTypeId.Value) ||

            (PriceDefinition.InviterId.HasValue && inviterId.HasValue &&
                PriceDefinition.InviterId.Value != inviterId.Value)
        );
}

现在我愿意将它们结合起来:

    public Expression<Func<IEntityPriceDefinition, bool>> IsMatchExpression(
        long? inviterId, long? routeId, long? luggageTypeId, long additionId)
    {
        return IsMatchExpression(inviterId, routeId, luggageTypeId) &&
                IsMatchExpression(additionId);
    }

此方法无法编译。我也有感觉我做错了什么。我该如何解决?

修改
我忘记了重要部分!问题已更新。

3 个答案:

答案 0 :(得分:1)

您必须直接使用表达式组件才能执行此操作。

public Expression<Func<IEntityPriceDefinition, bool>> IsMatchExpression(
        long? inviterId, long? routeId, long? luggageTypeId, long additionId)
{
    var a = IsMatchExpression(inviterId, routeId, luggageTypeId);
    var b = IsMatchExpression(additionId);
    var p = Expression.Parameter(typeof(IEntityPriceDefinition),"x");
    var c = Expression.AndAlso(Expression.Invoke(a,p),Expression.Invoke(b,p));
    var r = Expression.Lambda<Func<IEntityPriceDefinition, bool>>(c,p);
    return r;
}

通过从两个表达式中的每一个中删除.Body并使用新参数替换(使用ExpressionVisitor)参数,可以使这更复杂;并且可以更改两个工作方法中的每一个以将其参数绑定到ConstantExpression s,完全丢失lambda表达式语法。事实上,这些更改可能是必要的,以使表达能够与实体框架一起正常工作,但这需要一些时间让我在答案中发布。

另见How can I compose an Entity Framework query from smaller, resusable queries?

答案 1 :(得分:0)

好吧可能就像

var x = IsMatchExpression(inviterId, routeId, luggageTypeId)
var y = IsMatchExpression(additionId);
return arg => x(arg) && y(arg) 

答案 2 :(得分:0)

刚刚创建了组合方法:

   public Expression<Func<IEntityPriceDefinition, bool>> IsMatchExpression(
        long? inviterId, long? routeId, long? luggageTypeId, long additionId)
    {
    return x =>
        (inviterId.HasValue || routeId.HasValue || luggageTypeId.HasValue) &&
        (x.PriceDefinition.AdditionsPrices.Any(a => a.AdditionId == additionId)) &&
        !(
            (x.PriceDefinition.InviterId.HasValue && inviterId.HasValue &&
                PriceDefinition.InviterId.Value != inviterId.Value) ||

            (PriceDefinition.LuggageTypeId.HasValue && luggageTypeId.HasValue &&
                PriceDefinition.LuggageTypeId.Value != luggageTypeId.Value) ||

            (PriceDefinition.InviterId.HasValue && inviterId.HasValue &&
                PriceDefinition.InviterId.Value != inviterId.Value)
        );
}

不是最好的解决方案,但它有效。