Naor
Naor

Reputation: 24053

combine two expressions

I am trying to create an expression for using in entity framework query. I created two expressions:

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)
        );
}

And now I am willing to combine them:

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

This method doesn't compiles. I also have the feeling I did something wrong. How can I fix it?

EDIT:
I forgotenn importent part! the question updated.

Upvotes: 1

Views: 690

Answers (3)

Random832
Random832

Reputation: 38980

You'll have to work with the expression components directly to do this.

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;
}

This could be made more sophisticated by breaking out the .Body from each of the two expressions and replacing (using an ExpressionVisitor) the parameters with the new parameter; and each of your two working methods could be changed to bind their parameters into ConstantExpressions, losing the lambda expression syntax altogether. Those changes may in fact be necessary to make an expression that can work properly with entity framework, but this will take some time for me to work out to post in the answer.

See also How can I compose an Entity Framework query from smaller, resusable queries?

Upvotes: 1

Naor
Naor

Reputation: 24053

Just created combined method:

   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)
        );
}

Not the best solution but it works.

Upvotes: 0

Nicolas78
Nicolas78

Reputation: 5144

ok could it be sth like

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

?

Upvotes: 0

Related Questions