Я использую Linq-to-Entities, и для одного запроса требуется, чтобы свойство загружалось динамически. Запрос выглядит так:
var found = Context.IntegrateViews.GroupBy(x => x.TypeOfBed)
.Select(type => new TypeCounts
{ Name = type.Key, Count = type.Count() }).ToList();
Свойство, в котором выполняется предложение Group By, - TypeOfBed. Теперь я хочу запустить этот запрос для разных свойств, например, в следующий раз, когда я хочу его запустить, скажем, x.TypeOfChair и т.д. Для этого мне нужно иметь это свойство там динамически.
Я пытаюсь написать построитель выражений, который выглядит следующим образом.
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
}
И я намерен использовать его так:
var found = Context.IntegrateViews.GroupBy(PropertyLambda("TypeOfBed"))
.Select(type => new TypeCounts
{ Name = type.Key, Count = type.Count() }).ToList();
Но это не работает, я получаю ошибку времени компиляции, которая гласит:
ошибка CS0411: аргументы типа для метода "System.Linq.Queryable.GroupBy(System.Linq.IQueryable, System.Linq.Expressions.Expression>)" не могут быть выведены из использования. Попробуйте явно указать аргументы типа.
Что я здесь делаю неправильно?
Кажется, это проблема синтаксиса. Попробуй это:
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;
}
И использование:
var found = Context.IntegrateViews.GroupBy(PropertyLambda("TypeOfBed").Compile())
.Select(type => new TypeCounts
{ Name = type.Key, Count = type.Count() }).ToList();
Не тестировали, но как насчет следующего метода расширения?
private static Expression<Func<T, K>> MakeExpr<T, K>(this IQueryable<T> source, string property)
{
var type = typeof(T);
var arg = Expression.Parameter(type, "x");
var expr = Expression.Property(arg, property);
var lambda = Expression.Lambda<Func<T, K>>(expr, arg);
return lambda;
}
public static IQueryable<IGrouping<K, T>> GroupBy<T, K>(this IQueryable<T> source, string property)
{
return source.GroupBy(MakeExpr<T, K>(source, property));
}
Другой вариант - использовать 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();