12

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

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。但我不确定如何实现这一目标。所以我需要一些帮助。谢谢!我觉得动态语言在做这类工作时真的很出色!

来自 ScottGu 的引述

虽然编写类型安全的查询对于大多数场景来说都很棒,但在某些情况下,您希望灵活地动态构建查询

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

4

6 回答 6

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

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

于 2010-05-05T06:47:55.830 回答
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
{
}
于 2010-05-05T06:08:03.040 回答
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 已经很容易从表中获取所有对象,并且有一种简单的方法可以对这些对象进行排序。如果您学会正确使用提供的接口,您的查询也会更快并且使用更少的内存,因为您让数据库为您进行过滤而不是在客户端进行过滤。

于 2010-05-05T06:08:07.847 回答
4

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

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

于 2010-05-05T13:19:53.253 回答
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 扩展材料的链接也很酷!如果您需要快速编写代码,他们甚至有这个LinqKit

于 2010-05-05T17:04:03.680 回答
-1

这应该可以解决问题:

myEnumeration.OrderBy( itm => itm.SortOrder )
于 2010-05-05T06:07:39.483 回答