2014-10-24 12 views
6

Ich versuche, Paginierung und Sortierung mit generischen Repository zu implementieren. Wie nehme ich die Primärschlüsselspalte als Standardreihenfolge in DbSet?Apply OrderBy mit DbSet

public static string GetKeyField(Type type) 
{ 
    var allProperties = type.GetProperties(); 

    var keyProperty = allProperties.SingleOrDefault(p => p.IsDefined(typeof(KeyAttribute))); 

    return keyProperty != null ? keyProperty.Name : null; 
} 

public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string orderBy) 
{ 
    return source.GetOrderByQuery(orderBy, "OrderBy"); 
} 

public static IQueryable<T> OrderByDescending<T>(this IQueryable<T> source, string orderBy) 
{ 
    return source.GetOrderByQuery(orderBy, "OrderByDescending"); 
} 

private static IQueryable<T> GetOrderByQuery<T>(this IQueryable<T> source, string orderBy, string methodName) 
    { 
     var sourceType = typeof(T); 
     var property = sourceType.GetProperty(orderBy); 
     var parameterExpression = Expression.Parameter(sourceType, "x"); 
     var getPropertyExpression = Expression.MakeMemberAccess(parameterExpression, property); 
     var orderByExpression = Expression.Lambda(getPropertyExpression, parameterExpression); 
     var resultExpression = Expression.Call(typeof(Queryable), methodName, 
               new[] { sourceType, property.PropertyType }, source.Expression, 
               orderByExpression); 

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

Auf diese Weise können Sie passieren den Namen der Eigenschaft als String und bauen einen Ausdruck, der es geht auf den regulären LINQ OrderBy (:

DbSet = Context.Set<T>(); 

public IQueryable<T> GetAll(int pageNumber = 0, int pageSize = 10, string sortColumn = "") 
{ 
    return DbSet.OrderBy("how to use primary key column here").Skip(pageNumber * pageSize)Take(pageSize); 
} 
+0

Seitennotiz, ich bin mir ziemlich sicher, dass Sie 'Skip' dann' Take' wünschen würden – Jonesopolis

+0

@ Jonesy, Ja Danke, geändert ... –

Antwort

6

Ich habe diese Erweiterungsmethoden zu erreichen etwas ähnliches verwendet) Funktion. Also in Ihrem Fall wäre die Nutzung:

DbSet = Context.Set<T>(); 

public IQueryable<T> GetAll(int pageNumber = 0, int pageSize = 10, string sortColumn = "") 
{ 
    return DbSet.OrderBy(GetKeyField(typeof(T))).Skip(pageNumber * pageSize)Take(pageSize); 
} 

Dieses in Ihrem Entitätsklasse Ihr Schlüsselfeld übernimmt mit dem Key Attribute richtig eingerichtet.

+0

+1, sehr nützlich one ... –

+1

Große und flexible Lösung, gespeichert Ich habe viel Zeit. Vielen Dank! – Oleg

+0

Funktioniert wie ein Charme. Vielen Dank! –

0

Eine Möglichkeit wäre, alle Ihre Entitäten von einer Schnittstelle erben hat, dass Sie ihren Primärschlüsselwert abrufen kann:

public interface IIdentifiableEntity 
{ 
    public int Id {get; set;} 
} 

Dann würden Implementierungen wie:

public class User : IIdentifiableEntity 
{ 
    public int UserId {get; set;} 

    //other properties... 

    public int Id { get { return UserId; } set { UserId = value; } } 
} 

Dann wäre es sei so einfach wie die Bestellung von Id. Dieses Muster kann Ihnen auch in anderen Bereichen helfen.