генерировать EF orderby Выражение строкой

Я хочу сгенерировать выражение по параметру string, некоторый код:

private Expression<Func> Generate(string orderby) { switch (orderby) { case "Time": return t => t.Time; case "Money": return t => t.RewardMoney; default: return t => t.Id; } } 

затем назовите его:

 _context.Items.OrderBy(Generate("Money")); 

Но он не может скомпилироваться! Я изменяю T на объект.

 private Expression<Func> Generate(string orderby) 

Затем он может скомпилировать, но он не работает.

System.NotSupportedException: Невозможно ввести тип «System.Int32» для ввода «System.Object». LINQ to Entities поддерживает только листинг EDM-примитивов или типов перечислений.

Используя reflection и деревья выражений, вы можете предоставить параметры, а затем вызвать функцию OrderBy , вместо того, чтобы возвращать Expression> а затем вызывать OrderBy .

Обратите внимание: OrderBy является методом расширения и реализован как в classах System.Linq.Enumarable и в System.Linq.Queryable . Первый – для linq-to-objects, а последний для linq-to-entity . entity-framework нуждается в дереве выражений запроса, чтобы перевести его в команды SQL. Поэтому мы используем реализацию Queryable .

Это можно сделать с помощью метода расширения (пояснения добавлены как комментарии):

 public static IOrderedQueryable OrderBy( this IEnumerable query, string propertyName) { var entityType = typeof(TSource); //Create x=>x.PropName var propertyInfo = entityType.GetProperty(propertyName); ParameterExpression arg = Expression.Parameter(entityType, "x"); MemberExpression property = Expression.Property(arg, propertyName); var selector = Expression.Lambda(property, new ParameterExpression[] { arg }); //Get System.Linq.Queryable.OrderBy() method. var enumarableType = typeof(System.Linq.Queryable); var method = enumarableType.GetMethods() .Where(m => m.Name == "OrderBy" && m.IsGenericMethodDefinition) .Where(m => { var parameters = m.GetParameters().ToList(); //Put more restriction here to ensure selecting the right overload return parameters.Count == 2;//overload that has 2 parameters }).Single(); //The linq's OrderBy has two generic types, which provided here MethodInfo genericMethod = method .MakeGenericMethod(entityType, propertyInfo.PropertyType); /*Call query.OrderBy(selector), with query and selector: x=> x.PropName Note that we pass the selector as Expression to the method and we don't compile it. By doing so EF can extract "order by" columns and generate SQL for it.*/ var newQuery = (IOrderedQueryable)genericMethod .Invoke(genericMethod, new object[] { query, selector }); return newQuery; } 

Теперь вы можете вызвать эту перегрузку OrderBy как и любую другую перегрузку.
Например:

 var cheapestItems = _context.Items.OrderBy("Money").Take(10).ToList(); 

Что означает:

 SELECT TOP (10) {coulmn names} FROM [dbo].[Items] AS [Extent1] ORDER BY [Extent1].[Money] ASC 

Этот подход может быть использован для определения всех перегрузок методов OrderBy и OrderByDescending чтобы иметь селектор свойств string .

Вы можете попробовать преобразовать метод Generate в общий метод:

 private Expression> Generate(string orderby) { switch (orderby) { case "Time": return t => t.Time; case "Money": return t => t.RewardMoney; default: return t => t.Id; } } 

Таким образом, если вы вызываете этот метод, вам нужно указать тип свойства, которое вы хотите заказать:

 _context.Items.OrderBy(Generate("Money")); 

Теперь помните, что TResult может быть только примитивным типом или перечислением.

Interesting Posts

Возьмите сегмент массива в Java без создания нового массива в куче

Django – итерация числа для цикла шаблона

Как получить команды, выпущенные в сеансе ssh

Как устранить недостающие DLL и поврежденные системные файлы после обновления Windows-7?

Контролируемые в командной строке программы будильника для Mac OS X

Разница между виртуальным, переопределением, новым и закрытым переопределением

Preincrement быстрее, чем постинкремент в C ++ – правда? Если да, то почему?

32-битный максимальный размер окна с дискретной графической картой

Что делать с высокой эффективностью Java BigDecimal?

Обратный вызов, когда свойство зависимостей получает изменение xaml

Как я могу отображать использование памяти для каждого процесса, если я делаю «ps -ef»?

Невозможно использовать Intellij с созданной исходной папкой

Является ли регистр C # нечувствительным к оператору?

Как отключить определенное правило checkstyle для определенной строки кода?

Использование функции print () (версия функции) в Python2.x

Давайте будем гением компьютера.