Aamir
Aamir

Reputation: 15546

Writing a basic Expression Builder

I am using Linq-to-Entities and one query requires a property to be loaded dynamically. The query looks like this:

var found = Context.IntegrateViews.GroupBy(x => x.TypeOfBed)
                   .Select(type => new TypeCounts
                            { Name = type.Key, Count = type.Count() }).ToList();

The property on which Group By clause is being run is TypeOfBed. Now I want to run this query on different properties e.g., next time I want to run it on, let's say x.TypeOfChair and so on. For this, I need to have this property in there dynamically.

I am trying to write a Expression builder which is like this.

public Expression<Func<LookupFilterItem>> PropertyLambda(string propertyName)
{
    var param = Expression.Parameter(typeof(LookupFilterItem), "lookupItem");
    //type of x in above example is LookupFilterItem
    var propertyExpression = Expression.Property(param, propertyName);

    var returnExpr = Expression.Lambda<Func<LookupFilterItem>>(propertyExpression);
    return returnExpr;
    //If I Pass string "TypeOfBed" to this method, I am expecting it to return something like
    // lookupItem => lookupItem.TypeOfBed
}

And I intend to use it like this:

var found = Context.IntegrateViews.GroupBy(PropertyLambda("TypeOfBed"))
                   .Select(type => new TypeCounts
                            { Name = type.Key, Count = type.Count() }).ToList();

But this is not working, I am getting a compile time error which says:

error CS0411: The type arguments for method 'System.Linq.Queryable.GroupBy(System.Linq.IQueryable, System.Linq.Expressions.Expression>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

What am I doing wrong here?

Upvotes: 1

Views: 4487

Answers (2)

luqi
luqi

Reputation: 2909

Another option is to use LINQ Dynamic Query Library :

using System.Linq.Dynamic;

var found = Context.IntegrateViews.AsQueryable().GroupBy("new(TypeOfBed)", "it")
                   .Select(new (Key.TypeOfBed as Name, Count() as Count)).ToList();

Upvotes: 0

luqi
luqi

Reputation: 2909

This seems to be a syntax issue. Try this:

public Expression<Func<LookupFilterItem, string>> PropertyLambda(string propertyName)
    {
        var param = Expression.Parameter(typeof(LookupFilterItem), "lookupItem");
        var propertyExpression = Expression.Property(param, propertyName);
        var returnExpr = Expression.Lambda<Func<LookupFilterItem, string>>(propertyExpression, param);
        return returnExpr;
    }

And the usage:

var found = Context.IntegrateViews.GroupBy(PropertyLambda("TypeOfBed").Compile())
               .Select(type => new TypeCounts
                        { Name = type.Key, Count = type.Count() }).ToList();

Upvotes: 1

Related Questions