我有一个repository类,它将我的LINQ打包为SQL数据上下文.repository类是一个包含所有数据层逻辑(以及缓存等)的业务线类.

这是我的回购接口v1.

public interface ILocationRepository
{
    IList<Location> FindAll();
    IList<Location> FindForState(State state);
    IList<Location> FindForPostCode(string postCode);
}

但为了处理FindAll的分页,我正在考虑是否公开IQueryable&lt;ILocation&gt;而不是IList,以简化分页等情况下的接口.

从数据回购中公开IQueryable的利弊是什么?

非常感谢您的帮助.

推荐答案

专业人士;可组合性:

  • 呼叫者可以添加过滤器
  • 呼叫者可以添加寻呼
  • 呼叫者可以添加排序

犯人;不可测试性:

  • 您的存储库不再是适当的单元可测试性;您不能依赖a:it工作,b:what工作;
    • 调用方可以添加不可翻译的函数(即无TSQL映射;运行时中断)
    • 调用方可以添加过滤/排序,使其像狗一样工作
  • 因为调用者希望IQueryable<T>是可组合的,所以它排除了不可组合的实现——或者它迫使您为它们编写自己的查询提供程序
  • 这意味着你无法优化/配置DAL

为了稳定起见,我在我的存储库中 Select 了notIQueryable<T>Expression<...>.这意味着我知道存储库的行为,我的上层可以使用mock,而不用担心"实际的存储库支持这个吗?"(强制集成测试).

我仍然在存储库中使用IQueryable<T>inside,但不会超出边界.我发了大约more thoughts on this theme here条.在存储库界面上放置分页参数同样容易.您甚至可以使用扩展方法(在接口上)添加optional个分页参数,这样具体的类只有1个方法要实现,但调用方可能有2到3个重载可用.

.net相关问答推荐

带有ASP.NET核心的Angular 项目模板.API试验

如何手动注入依赖注入

.Net MAUI Android 无法与 API localhost 对话

使属性只能通过绑定的 Editor(component) 编辑

Erlang 的让它崩溃的哲学 - 适用于其他地方吗?

无法加载文件或程序集 Microsoft.Extensions.DependencyInjection.Abstractions,版本 = 1.1.0.0

有没有办法以编程方式最小化窗口

通用枚举到int的C#非装箱转换?

.NET 4.0 中有内置的二叉搜索树吗?

如何右对齐 DataGridView 列中的文本?

如何判断一个类型是否是简单类型?即持有一个单一的价值

如何等到远程 .NET 调试器附加

析构函数、dispose 和 finalize 方法的区别

如何将 XPath 与 XElement 或 LINQ 一起使用?

如何在 RabbitMQ 中设置重试次数?

.NET 进程间通信的最佳 Select 是什么?

如何获取命名空间中的所有类?

SqlBulkCopy 的推荐批量大小是多少?

在 try/catch/finally 中等待的一个很好的解决方案?

如何在 ASP.NET MVC 中重定向到动态登录 URL