2014-10-24 4 views
6

Я пытаюсь реализовать разбиение на страницы и сортировку с общим хранилищем. Как перенести первичный столбец по умолчанию по столбцу в DbSet?Apply OrderBy с DbSet

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

сторона примечание, я уверен, что вы захотите «Пропустить», затем «Take» – Jonesopolis

+0

@ Jonesy, да Спасибо, изменено ... –

ответ

6

Я использовал эти методы расширения для достижения нечто подобное:

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); 
    } 

Это позволяет передать имя свойства в виде строки и создать выражение, которое она проходит в очередной LINQ OrderBy (). Так что в вашем случае использование будет:

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); 
} 

Это предполагает ваше ключевое поле в классе объекта правильно оформлен с атрибутом Key.

+0

+1, очень полезно ... –

+1

Отличное и гибкое решение, сохраненное я много времени. Спасибо! – Oleg

+0

Работает как шарм. Спасибо! –

0

Один из способов будут иметь все ваши объекты наследуют от какого-то интерфейса, который позволяет получить их значение первичного ключа:

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

Тогда реализация будет как:

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

    //other properties... 

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

Тогда бы быть таким же простым, как заказать по номеру Id. Этот шаблон может помочь вам и в других областях.