开发者

How to OrderBy on a generic IEnumerable (IEnumerable<T>) using LINQ in C#?

In my generic repository I have below method:

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

T is a Linq to Sql class and I want to be able to OrderBy on a particular property (i.e. int SortOrder). Say if T has property name "SortOrder" then do OrderBy on this property. But I am not sure how I can achieve this. So I need some helps. Thank you! I feel like dynamic languages really shines in doing this kind of jobs!

Quote from ScottGu:

While writing type-safe queries is great for most scenarios, there are cases where you want the flexibility to dynamically construct queries on the fly

And this is exactly the problem I am facing and I am wondering if this linq dynamic helper can be made into official .NET library.


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

Usage:

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

Unfortunately, you have to supply the type of the key. Unless you start messing with the expressions.


To get this to work you would need to define a constraint. For example:

public interface IOrderable
{
    int SortOrder { get; }
}

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

Now you can use ts.OrderBy(t => t.SortOrder) inside the method body. All the classes you intend to use with this method must then implement this interface.

However as you pointed out LINQ To SQL classes do not implement this interface. I would recommend that you do not take this approach if using LINQ to SQL. With LINQ to SQL it already is very easy to fetch all objects from a table and there is an easy way to order these objects. If you learn to use the provided interfaces correctly your queries will also be much faster and use less memory because you get the database to do filtering for you instead of filtering on the client.


You can't do it generically, unless you constrain the type parameter T to a type that has the property you want to sort on. For instance, if you have an interface named IHaveTheProperty, then you can do:

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

But without a constraint, you can only use the methods of the System.Object type.


LINQ to SQL classes are created partial. That means that you can create another class part to force one of those classes to implement your interface:

public partial class Address : IHaveTheProperty
{
}


You could use the dynamic Linq library that would let you construct the OrderBy dynamically: http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

Personally I always have my repositories return IQueryable then the consumer can handle building up additional filtering, ordering or projections as needed.


If I was asked to do this I could do something like this:

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

And

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

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

or in .net 4 make the parameter optional and accomplish the same in a single method. You will need a predicate builder like logic to help your client code build delegates on the fly. The link by Jeffrey on my comment kinda illustrates all this stuff! And this link from the extended material from C#3.0 in a nutshell is cool too! If you need to crank the code quick they even have this LinqKit


this should do the trick:

myEnumeration.OrderBy( itm => itm.SortOrder )
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜