【问题标题】:Not exposing IQueryable and not violating OC principle [closed]不暴露 IQueryable 且不违反 OC 原则 [关闭]
【发布时间】:2017-01-04 05:52:01
【问题描述】:

最近几天我正在阅读有关存储库模式的信息,每个谈论它的人都不要像这样从存储库中公开 IQueryable(例如 herehere):

public interface ICustomersRepository
{
    IQueryable<Customer> Customers{ get; }
}

并且为避免这种情况被大量开发人员所接受。

但是当涉及从 UI 过滤大量数据和自定义过滤器时(例如具有 10 多个过滤器选项的报告,用于搜索超过 100 万条记录的数据)是 IQueryable 吗?

特别是当有一个框架并且其他低级开发人员正在使用存储库来开发自定义报告时。他们不能总是将 GetAll 用于此目的。

正如thisthis 等其他线程中提到的,我应该为我的存储库中的每个报告提供方法,并且它们应该返回IEnumerable。以下是我不清楚的地方:

如果我有一个新报告,我必须为此更改我的存储库并添加一个新方法。如果我更改我的存储库,我就违反了Open/Close principle

这是我的问题:我不想公开 Iqueryable,另一方面,我不想更改每个报告的存储库。

【问题讨论】:

  • 不返回 IQueryable,而是取一个,可以用作过滤器。比如public SomeType[] Get(IQueryable&lt;SomeType&gt; filter)这个好用的var result = someTypeRepo.Get(x =&gt; x.Id &gt; 0)
  • 谢谢你,实际上可以轻松工作
  • 您也可以采用 IQueryables 来表达您希望包含在结果中的导航属性。
  • @这对我现在有帮助,但毕竟我必须返回所有数据进行过滤

标签: c# entity-framework repository-pattern unit-of-work


【解决方案1】:

存储库是对数据访问层 (DAL) 的抽象。在 Java 中,它们也称为 DAO(数据访问对象)。因此,在存储库中公开IQueryable&lt;T&gt; 是不好的做法,因为这个原因,您将 LINQ 查询绑定到客户端代码。

因此,要修复它,您应该创建一个对象,该对象将遵循命令模式以及您支持的所有过滤选项。然后返回一个List&lt;T&gt; 或任何你想使用的排序集合(也许IList&lt;T&gt; 更合适)。

一个例子

class BookFilter
{
    public string NameStartsWith { get; set; }
    public string ISBN { get; set; }
    public DateTime PublishedAfter { get; set; }
    // ....
}

public interface IBookRepository  
{
    IList<Book> Filter(BookFilter filter);
}

【讨论】:

  • 感谢您的回复,正如您对每份报告所说的那样,我应该更改我的存储库?因为客户总是要求新的报告,我应该更改我的存储库,我认为打开关闭主体很暴力
  • 如果您正在做的是报告,这可能不是一个舒适的选择。我正在回答你问的情况。即使您展示的是需求发生变化的场景,BookFilter 也会相应地支持您以前不支持的新过滤器。与存储库模式保持距离,如果您正在做的是报告,也许您可​​能会选择直接使用 IQueryable,如果报告可能会更改或增长,则更多。
  • 谢谢你,这正是我困惑的地方
  • 顺便说一下,我已经更新了我的问题以供将来明确
猜你喜欢
  • 1970-01-01
  • 2013-01-01
  • 2018-04-09
  • 1970-01-01
  • 2018-06-19
  • 2014-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多