我有一个存储库类,它包装了我的 LINQ to SQL 数据上下文。存储库类是包含所有数据层逻辑(以及缓存等)的业务线类。
这是我的 repo 接口(interface)的 v1。
public interface ILocationRepository
{
IList<Location> FindAll();
IList<Location> FindForState(State state);
IList<Location> FindForPostCode(string postCode);
}
但是为了处理 FindAll 的分页,我正在讨论是否公开 IQueryable 而不是 IList 以简化分页等情况的接口(interface)。
从数据存储库中公开 IQueryable 的优缺点是什么?
非常感谢任何帮助。
优点;可组合性:
- 来电者可以添加过滤器
- 调用者可以添加寻呼
- 来电者可以添加排序
- 等等
缺点;不可测试性:
- 您的存储库不再适合进行单元测试;你不能依赖 a:它工作,b:它做什么;
- 调用者可以添加一个不可翻译的函数(即没有 TSQL 映射;在运行时中断)
- 调用者可以添加一个过滤器/排序,使其像狗一样执行
- 因为来电者期望
IQueryable<T>
为了可组合,它排除了不可组合的实现 - 或者它会强制您为它们编写自己的查询提供程序
- 这意味着您无法优化/分析 DAL
为了稳定性,我已采取不公开IQueryable<T>
或 Expression<...>
在我的存储库上。这意味着我知道存储库的行为方式,并且我的上层可以使用模拟而不用担心“实际的存储库是否支持这个?” (强制集成测试)。
我还在用IQueryable<T>
etc inside 存储库 - 但不超过边界。我发布了一些 more thoughts on this theme here .将分页参数放在存储库界面上同样容易。您甚至可以使用扩展方法(在接口(interface)上)添加可选分页参数,这样具体类只有 1 个方法要实现,但可能有 2 或 3 个重载可供调用者使用。