c#generic orderby

时间:2013-02-25 10:14:04

标签: linq entity-framework generics sql-order-by expression

在我的base-repository类

我编写了这个函数,可以从数据库中检索已排序的数据集合。 T是在类级别定义的通用

public abstract class RepositoryBase<T> 
        where T : class

代码是这样的:

public IList<T> GetAll<TKey>(Expression<Func<T, bool>> whereCondition, Expression<Func<T, TKey>> sortCondition, bool sortDesc = false)
        {
            if (sortDesc)
                return this.ObjectSet.Where(whereCondition).OrderByDescending(sortCondition).ToList<T>();

            return this.ObjectSet.Where(whereCondition).OrderBy(sortCondition).ToList<T>() ;
        }

我的目标是引入一个泛型排序参数,以便我可以这样调用该函数:

repo.GetAll (model=>model.field>0, model=>model.sortableField, true)

我的意思是我可以直接通过匿名函数指定排序字段,因此使用Intellisense ...

不幸的是,此函数不起作用,因为最后一个代码行在编译时生成错误。

我也试着打电话:

repo.GetAll<Model> (model=>model.field>0, model=>model.sortableField, true)

但这不起作用。

我该如何编写功能以达到我的目标?

我正在使用EF 5,c#,. NET 4.5

1 个答案:

答案 0 :(得分:1)

您正在使用ObjectSet来实现IQueryable<T>。通过System.Linq.Queryable上接受Expression<Func<参数的方法进行了扩展。使用那些Expression参数是正确的,因为您打算在数据库中执行,而不是在本地。

  • Func是一个匿名委托,一个.net方法。
  • Expression是一棵树,可以编译成Func,也可以翻译成Sql或其他东西。

您向我们展示了该方法的一个非常抽象的用法,但没有实际使用该方法或编译器错误。我怀疑你可能犯的错误是混淆了两个类型的参数。

你说:

repo.GetAll<Model> (model=>model.field>0, model=>model.sortableField, true)

但此方法的此泛型参数表示sortableField的类型。如果sortableField不是模型 - 这是错误的。

相反,你应该做这样的事情:

Repository<Person> myRepo = new Repository<Person>();
myRepo.GetAll<DateTime>(p => p.Friends.Count() > 3, p => p.DateOfBirth, true);

如果指定排序类型会破坏您的预期使用模式,请考虑使用IOrderer隐藏该键:Store multi-type OrderBy expression as a property