如何在C#中使用LINQ在一个通用的IEnumerable(IEnumerable <t>)上进行排序?</t>

时间:2010-05-05 06:05:05

标签: c# linq sql-order-by generic-list

在我的通用存储库中,我有以下方法:

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

T是Linq to Sql类,我希望能够在特定属性(即int SortOrder)上使用OrderBy。假如T具有属性名称“SortOrder”,则在此属性上执行OrderBy。但我不确定如何实现这一目标。所以我需要一些帮助。谢谢!我觉得动态语言真的很适合做这种工作!

Quote from ScottGu

  

编写类型安全的查询时   对大多数场景都很有用   你想要灵活性的情况   动态构建查询   苍蝇

这正是我面临的问题,我想知道这个linq动态助手是否可以制作成官方的.NET库。

6 个答案:

答案 0 :(得分:7)

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

不幸的是,您必须提供密钥的类型。除非你开始搞乱表达。

答案 1 :(得分:5)

除非将类型参数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类partial。这意味着您可以创建另一个类部件来强制其中一个类实现您的接口:

public partial class Address : IHaveTheProperty
{
}

答案 2 :(得分:5)

要使其工作,您需要定义约束。例如:

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,从表中获取所有对象非常容易,并且可以通过简单的方法来订购这些对象。如果您学会正确使用提供的接口,您的查询也会更快,并且使用更少的内存,因为您让数据库为您进行过滤而不是在客户端上进行过滤。

答案 3 :(得分:4)

您可以使用动态Linq库来动态构建OrderBy:http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

我个人总是让我的存储库返回IQueryable,然后消费者可以根据需要处理额外的过滤,排序或预测。

答案 4 :(得分:0)

如果我被要求这样做,我可以这样做:

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使参数可选,并在单个方法中完成相同的操作。您将需要一个类似逻辑的谓词构建器来帮助您的客户端代码动态构建委托。杰弗里对我评论的链接有点说明了所有这些内容!而来自C#3.0扩展材料的这个link简直太酷了!如果您需要快速启动代码,他们甚至可以使用LinqKit

答案 5 :(得分:-1)

这应该可以解决问题:

myEnumeration.OrderBy( itm => itm.SortOrder )