我正在尝试创建一个存储库类,其中包含一个基于“sort”参数对结果进行排序的方法。我需要将它作为参数传递,因为我试图非常严格,我的存储库不返回IQueryable并且只返回List。问题是我不知道如何制作它以满足以下要求:
这是否可能,或者存储库允许返回订购是否无用?存储库是否应该只能执行CRUD操作?也许返回IQueryable会是最好的选择吗?
答案 0 :(得分:7)
也许你需要这样的东西:
public class Ordering<T>
{
private readonly Func<IQueryable<T>, IOrderedQueryable<T>> transform;
private Ordering(Func<IQueryable<T>, IOrderedQueryable<T>> transform)
{
this.transform = transform;
}
public static Ordering<T> Create<TKey>
(Expression<Func<T, TKey>> primary)
{
return new Ordering<T>(query => query.OrderBy(primary));
}
public Ordering<T> ThenBy<TKey>(Expression<Func<T, TKey>> secondary)
{
return new Ordering<T>(query => transform(query).ThenBy(secondary));
}
// And more for the descending methods...
internal IOrderedQueryable<T> Apply(IQueryable<T> query)
{
return transform(query);
}
}
然后,客户端可以创建要传递到存储库的Ordering<T>
,并且存储库可以使用Apply
调用IQueryable<T>
。这有意义吗?
样品(稍微傻)使用:
var ordering = Ordering<FileInfo>.Create(fi => fi.Length)
.ThenBy(fi => fi.Name);
答案 1 :(得分:3)
这是有争议的,但我认为您的存储库应该只返回数据。让你的消费类担心集合的排序。
这背后的思考过程非常简单,消费类无论如何都要决定订单。因此,他们可以将其传递给您的存储库中的手工制作的orderby生成器并让它完成工作,或者他们可以只使用linq并从存储库中订购它们返回的集合。我认为后一个选项更容易实现,更不容易出错,并且在阅读代码时更有意义,但我再一次认为我的观点是有争议的。
答案 2 :(得分:2)
我认为直接返回IQueryable<T>
通常是最佳选择。
例如,假设您有一个查询数据库以返回特定表或视图的方法。如果存储库的客户端只需要前10条记录,并且具有您不期望的自定义条件和排序,则可以通过返回IQueryable<T>
来允许此操作。客户只需添加.Where(...).OrderBy(...).Take(10);
使用IQueryable<T>
,跨数据层的调用将自动适应,并且只会拉出10条记录。如果您返回List,则数据库查询将提取每条记录,然后需要在您的应用程序中进行过滤。
这增加了巨大的处理/网络/等开销,没有任何正当理由。