简体   繁体   中英

Pass a parameter to the reusable Expression in a Entity Framework

I want to declare and reuse Expression with filter by variable y. In a method I have something like following:

Expression<Func<Item, int, bool>> exFilter = (x, y) => x.Item.Id == y;

Further on, in a code I'm trying to use declared expression (exFilter)

return context.Item.Select(x => new { data = exFilter.Where(exFilter))

Q: How do I pass parameter to the exFilter? I want to do select filtered by every item in a list(x).

This is just a sample what I'm trying to figure out. The problem and query is much bigger and complicated.

You can use LinqKit to reuse the expression that you have. Here is an example:

var result =
    context.Item //The DbSet
    .AsExpandable() //This method is defined in LinqKit and allows for expression expansion
    .Where(x => exFilter.Invoke(x, 2)) //LinqKit will know how to translate this into an expression
    .ToList();

I am using the value 2 here as an example.

You can rewrite you code like this:

Expression<Func<Item, bool>> exFilter(int y){ return (x) => x.item.Id == y;}

And use it like this:

int paramY = 456;
return context.Item.Select(exFilter(paramY))

You can try something like this:

public class Item
{
    public Item(String str, Int32 @int)
    {
        this.StrValue = str;
        this.IntValue = @int;
    }
    public String StrValue { get; }
    public Int32 IntValue { get; }
    public override string ToString() => 
        $"{this.IntValue} = '{this.StrValue}'";
}


public static class ExpressionExtensions
{
    public static Expression<Func<TItem, TResult>> Curry<TItem, TCurry, TResult>(
        this Expression<Func<TItem, TCurry, TResult>> function,
        TCurry value)
    {
        if (function == null)
            throw new ArgumentNullException(paramName: nameof(function));

        var itemParameter = Expression.Parameter(typeof(TItem));
        var valueConstant = Expression.Constant(value);

        return Expression.Lambda<Func<TItem, TResult>>(
            Expression.Invoke(
                function,
                new Expression[]
                {
                    itemParameter,
                    valueConstant
                }),
            new[] { itemParameter });
    }
}

...

var items = new[]
{
    new Item("one", 1),
    new Item("two", 2),
    new Item("two again", 2),
};

Expression<Func<Item, Int32, Boolean>> predicate = (item, intValue) =>
    item.IntValue == intValue;

var curriedPredicate = predicate.Curry(2);

var filtered = items
    .AsQueryable<Item>()
    .Where(curriedPredicate)
    .ToArray();

foreach (var item in filtered)
{
    Console.WriteLine(item);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM