9

Błąd jestNie można sortować z nazwy właściwości w LINQ OrderBy

LINQ podmiotów nie rozpozna metody 'System.Object GetValue (System.Object, System.Object [])' sposobu i tej metody nie można przetłumaczyć na wyrażenie składowania.

Mój kod jest

public static GridResult GetAllUsers(int count, int tblsize,string sortcreteria) 
{ 
     using (UserEntities entity = new UserEntities()) 
     { 

      var data = entity.User_Details.Take(count) 
.OrderBy(i =>.GetType().GetProperty(sortcreteria).GetValue(i,null)) 
.Skip(tblsize).ToList(); 
      result.DataSource = data; 
      result.Count = entity.User_Details.Count(); 
     } 
     return result; 
} 

Jak sortować z nazwy właściwości jako ciąg?

+0

może rosnąco lub malejąco –

+0

bardzo podobny http pytanie: //stackoverflow.com/q/15973414/413032 –

+0

"LINQ to Entities nie rozpoznaje metody" oznacza, że ​​nie mogę przetłumaczyć wyrażenia reflection na SQL. –

Odpowiedz

28

Wystarczy dodać następujące rozszerzenia do kodu i jesteś dobry, aby przejść:

using System.Linq; 
using System.Linq.Expressions; 
using System; 

namespace SomeNameSpace 
{ 
    public static class SomeExtensionClass 
    { 
     public static IQueryable<T> OrderByField<T>(this IQueryable<T> q, string SortField, bool Ascending) 
     { 
      var param = Expression.Parameter(typeof(T), "p"); 
      var prop = Expression.Property(param, SortField); 
      var exp = Expression.Lambda(prop, param); 
      string method = Ascending ? "OrderBy" : "OrderByDescending"; 
      Type[] types = new Type[] { q.ElementType, exp.Body.Type }; 
      var mce = Expression.Call(typeof(Queryable), method, types, q.Expression, exp); 
      return q.Provider.CreateQuery<T>(mce); 
     } 
    } 

}

Zastosowanie:

.OrderByField(sortcriteria, true) 

Edit:

wsparcie dla metody ThenBy jednak następujące metody zwrócenie IOrderedQueryable powinien dbać o wszystko:

public static class SomeExtensionClass 
{ 
    private static IOrderedQueryable<T> OrderingHelper<T>(IQueryable<T> source, string propertyName, bool descending, bool anotherLevel) 
    { 
     var param = Expression.Parameter(typeof(T), "p"); 
     var property = Expression.PropertyOrField(param, propertyName); 
     var sort = Expression.Lambda(property, param); 

     var call = Expression.Call(
      typeof(Queryable), 
      (!anotherLevel ? "OrderBy" : "ThenBy") + (descending ? "Descending" : string.Empty), 
      new[] { typeof(T), property.Type }, 
      source.Expression, 
      Expression.Quote(sort)); 

     return (IOrderedQueryable<T>)source.Provider.CreateQuery<T>(call); 
    } 

    public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string propertyName) 
    { 
     return OrderingHelper(source, propertyName, false, false); 
    } 

    public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string propertyName, bool descending) 
    { 
     return OrderingHelper(source, propertyName, descending, false); 
    } 

    public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> source, string propertyName) 
    { 
     return OrderingHelper(source, propertyName, false, true); 
    } 

    public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> source, string propertyName, bool descending) 
    { 
     return OrderingHelper(source, propertyName, descending, true); 
    } 
} 
+0

Nie powinien zwracać '' IOrderedQueryable''? – pomber

+2

Dzięki za wskazanie. Edytowałem kod, więc obsługuje on metodę 'ThenBy' dostarczaną przez' IOrderedQueryable'. – Ziad

+0

Świetne rozwiązanie. Naprawdę pomogło mi to, gdy robiłem api web z metodą wyszukiwania. – Lithium

5

Można spróbować to zrobić używając (nieco stary) Dynamic LINQ Biblioteka:

var data = entity.User_Details 
    .Take(count) 
    .OrderBy(sortcriteria) 
    .Skip(tblsize) 
    .ToList(); 

Ewentualnie można jeszcze uporządkować kolejność korzystania z oryginalnego zapytania poprzez przesuwanie przedmiotów w pamięci pierwsze, od LINQ do podmioty dostawca nie może tłumaczyć wywołań API Reflection do SQL:

var data = entity.User_Details 
    .Take(count) 
    .Skip(tblsize) 
    .AsEnumerable() 
    .OrderBy(i => i.GetType().GetProperty(sortcriteria).GetValue(i, null)) 
+0

Czy sądzisz, że GetValue (i, null) podaje nazwę nieruchomości? Błąd mówi "LINQ do Entities nie rozpoznaje" tak myślisz, że twój będzie zwracał się do SQL? –

+0

Proszę mnie oświecić. Jak to działa w Linq2Entities? –

+0

@ DavutGürbüz Wywołanie 'AsEnumerable()' (lub dowolnej z metod 'ToList()', 'ToArray()' i tak dalej) wymusza zapytanie LINQ do bazy danych, co spowoduje przesunięcie wynikowej sekwencji do pamięci. Stamtąd możesz łatwo zamawiać obiekty według wartości właściwości o określonej nazwie. –

Powiązane problemy