Как к OrderBy на универсальном IEnumerable (IEnumerable <T>) использующий LINQ в C#?

В моем универсальном репозитории я имею ниже метода:

public virtual IEnumerable GetAll() where T : class
{
    using (var ctx = new DataContext())
    {
        var table = ctx.GetTable().ToList();
        return table;
    }
}

T является Linq к классу Sql, и я хочу смочь к OrderBy на особом свойстве (т.е. международный SortOrder). Скажите, имеет ли T имя свойства "Порядок сортировки", затем делают OrderBy на этом свойстве. Но я не уверен, как я могу достигнуть этого. Таким образом, мне нужно, некоторые помогают.Спасибо! Я чувствую, что динамические языки действительно сияют в выполнении этого вида заданий!

Кавычка от ScottGu:

В то время как запись безопасных с точки зрения типов запросов является большой для большинства сценариев, существуют случаи, где Вы хотите, чтобы гибкость динамично создала запросы на лету

И это - точно проблема, с которой я сталкиваюсь, и я задаюсь вопросом, может ли этот linq динамический помощник быть превращен в официальную библиотеку.NET.

12
задан Jeff 5 May 2010 в 22:55
поделиться

6 ответов

Вы можете использовать динамическую библиотеку Linq, которая позволит вам сконструировать OrderBy динамически: http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

Лично я всегда заставляю свои хранилища возвращать IQueryable, тогда потребитель может сам создавать дополнительную фильтрацию, упорядочивание или проекции по мере необходимости.

4
ответ дан 2 December 2019 в 18:18
поделиться

Вы не можете сделать это в общем случае, если не ограничите тип параметр T к типу, имеющему свойство, по которому вы хотите выполнить сортировку. Например, если у вас есть интерфейс с именем IHaveTheProperty , тогда вы можете:

public virtual IEnumerable<T> GetAll<T>() where T : class, IHaveTheProperty
{
    using (var ctx = new DataContext())
    {
        ctx.ObjectTrackingEnabled = false;
        var table = ctx.GetTable<T>().ToList().AsReadOnly().OrderBy(t=>t.TheProperty);
        return table;
    }
}

Но без ограничения вы можете использовать только методы типа System.Object .


Классы LINQ to SQL создаются частично . Это означает, что вы можете создать другую часть класса, чтобы заставить один из этих классов реализовать ваш интерфейс:

public partial class Address : IHaveTheProperty
{
}
5
ответ дан 2 December 2019 в 18:18
поделиться

это должно помочь:

myEnumeration.OrderBy( itm => itm.SortOrder )
-1
ответ дан 2 December 2019 в 18:18
поделиться
public IEnumerable<T> GetAll<T,K>(Expression<Func<T,K>> sortExpr)
{
  using (var ctx = new DataContext())
  {
    ctx.ObjectTrackingEnabled = false;
    var table = ctx.GetTable<T>().OrderBy(sortExpr).ToList();
    return table;
  }
}

Использование:

var t = GetAll<Foo, int>(x => x.Bar);

К сожалению, вы должны указать тип ключа. Если только вы не начнете возиться с выражениями.

7
ответ дан 2 December 2019 в 18:18
поделиться

Если бы меня попросили сделать это, я бы сделал что-то вроде этого:

public virtual IEnumerable<T> GetAll<T>() where T : class
{
    using (var ctx = new DataContext())
    {
        var table = ctx.GetTable<T>().ToList();
        return table;
    }
}

и

publuc virtual IEnumerable<T> GetAll<T>(Func<T,bool> orderByClause) where T:class{

return GetAll<T>().OrderBy(orderByClause);
}

или в .net 4 сделать параметр необязательным и выполнить то же самое в одном методе. Вам понадобится логика типа predicate builder, чтобы помочь вашему клиентскому коду создавать делегаты на лету. Ссылка Джеффри на мой комментарий как бы иллюстрирует все эти вещи! И эта ссылка из расширенного материала из C#3.0 в двух словах - тоже круто! Если вам нужно быстро разобрать код, у них даже есть вот это LinqKit

0
ответ дан 2 December 2019 в 18:18
поделиться

Чтобы это работало, вам нужно определить ограничение. Например:

public interface IOrderable
{
    int SortOrder { get; }
}

public virtual IEnumerable<T> GetAll<T>() where T : class, IOrderable
{
    ...
}

Теперь вы можете использовать ts.OrderBy (t => t.SortOrder) внутри тела метода. Все классы, которые вы собираетесь использовать с этим методом, должны затем реализовать этот интерфейс.

Однако, как вы указали, классы LINQ To SQL не реализуют этот интерфейс. Я бы рекомендовал вам не применять этот подход при использовании LINQ to SQL. С LINQ to SQL уже очень легко получить все объекты из таблицы, и есть простой способ упорядочить эти объекты. Если вы научитесь правильно использовать предоставленные интерфейсы, ваши запросы также будут намного быстрее и будут использовать меньше памяти, потому что вы заставите базу данных выполнять фильтрацию вместо фильтрации на клиенте.

5
ответ дан 2 December 2019 в 18:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: