Хорошо, я признаю, что я еще не совсем "получил" лямбда-выражения и деревья выражений LINQ; многое из того, что я делаю, — это вырезание и вставка и просмотр того, что работает. Я просмотрел много документации, но так и не нашел своего момента "ага".
С учетом сказанного...
Я пытаюсь динамически добавить выражение GroupBy в выражение Linq. Я следил за вопросом здесь: Нужна помощь в создании Linq.Expression для Enumerable.GroupBy
и попытался реализовать то, что я там увидел.
Во-первых, у меня есть классы сущностей для моей базы данных и таблица с именем ObjCurLocViewNormalized.
У меня есть метод, который выполняет первоначальный вызов,
public IQueryable<ObjCurLocViewNormalized> getLocations()
{
IQueryable<ObjCurLocViewNormalized> res = (from loc in tms.ObjCurLocViewNormalized
select loc);
return res;
}
поэтому я могу позвонить:
IQueryable<MetAmericanLinqDataModel.ObjCurLocViewNormalized> locations = american.getLocations();
Пока нет проблем.
Теперь я хочу сгруппировать по произвольному столбцу с помощью такого вызова:
var grouped = locations.addGroupBy(childLocationFieldName);
Прямо сейчас у меня есть метод:
static public System.Linq.IQueryable<System.Linq.IGrouping<string, TResult>> addGroupBy<TResult>(this IQueryable<TResult> query, string columnName)
{
var providerType = query.Provider.GetType();
// Find the specific type parameter (the T in IQueryable<T>)
var iqueryableT = providerType.FindInterfaces((ty, obj) => ty.IsGenericType && ty.GetGenericTypeDefinition() == typeof(IQueryable<>), null).FirstOrDefault();
var tableType = iqueryableT.GetGenericArguments()[0];
var tableName = tableType.Name;
var data = Expression.Parameter(iqueryableT, "query");
var arg = Expression.Parameter(tableType, tableName);
var nameProperty = Expression.PropertyOrField(arg, columnName);
var lambda = Expression.Lambda<Func<TResult, string>>(nameProperty, arg);
var expression = Expression.Call(typeof(Enumerable),
"GroupBy",
new Type[] { tableType, typeof(string) },
data,
lambda);
var predicate = Expression.Lambda<Func<TResult, String>>(expression, arg); // this is the line that produces the error I describe below
var result = query.GroupBy(predicate).AsQueryable();
return result;
}
Все компилируется нормально, но при запуске получаю ошибку:
System.ArgumentException: Expression of type 'System.Collections.Generic.IEnumerable`1[System.Linq.IGrouping`2[System.String,MetAmericanLinqDataModel.ObjCurLocViewNormalized]]' cannot be used for return type 'System.String'
и ошибка исходит из этой строки:
var predicate = Expression.Lambda<Func<TResult, String>>(expression, arg);
Я копирую и адаптирую этот код из успешной работы, которую я проделал в динамически добавленных предложениях Where к выражению. Так что здесь я как бы ковыряюсь в темноте.
Если кто-нибудь может помочь пролить свет на это, очевидно, опубликовать полный рабочий код и сделать все, что я думаю за меня, было бы здорово :), но если бы вы могли просто изложить, почему это неправильно, или как обернуть мою голову вокруг этих концепций, это было бы здорово. Если вы можете указать на документацию, которая действительно может помочь преодолеть разрыв между основами лямбда-выражений и построением динамических деревьев выражений, это было бы здорово. В моих знаниях явно есть большие пробелы, но я думаю, что эта информация может быть полезна другим.
спасибо всем за ваше время, и, конечно, если я найду ответ в другом месте, я опубликую его здесь.
Спасибо еще раз.
Дон
predicate
используетFunc<TResult, string>
? Ваше выражение возвращаетIGrouping
, которое не являетсяstring
. - person Kirk Woll   schedule 08.10.2010.GroupBy
с лямбда-предикатом, который вы передаете it. Сейчас у меня нет времени отвечать дальше, но если этот вопрос все еще останется без ответа через час, я сделаю более тщательный удар. - person Kirk Woll   schedule 08.10.2010