asp.net - 存储库模式最佳实践

标签 asp.net repository-pattern repository repository-design

因此,我在应用程序中实现存储库模式,并在我对该模式的理解中遇到了两个“问题”:

  1. 查询 - 我已阅读有关在使用存储库时不应使用 IQueryable 的回复。但是,很明显您希望每次调用方法时都不会返回完整的对象列表。是否应该实现?如果我有一个名为 List 的 IEnumerable 方法,那么 IQueryable 的一般“最佳实践”是什么?它应该/不应该有哪些参数?

  2. 标量值 - 返回单个标量值而不必返回整个记录的最佳方法(使用存储库模式)是什么?从性能的角度来看,在整行中仅返回单个标量值不是更有效吗?

最佳答案

严格来说,存储库提供用于获取/放置域对象的集合语义。它提供了围绕物化实现(ORM、手动、模拟)的抽象,以便域对象的使用者与这些细节解耦。在实践中,存储库通常抽象对实体的访问,即具有身份的域对象,并且通常是持久生命周期(在 DDD 风格中,存储库提供对聚合根的访问)。

存储库的最小接口(interface)如下:

void Add(T entity);
void Remove(T entity);
T GetById(object id);
IEnumerable<T> Find(Specification spec);

尽管您会看到命名差异以及 Save/SaveOrUpdate 语义的添加,但以上是“纯粹”的想法。您将获得 ICollection 添加/删除成员以及一些查找器。如果您不使用 IQueryable,您还会在存储库中看到查找方法,例如:

FindCustomersHavingOrders();
FindCustomersHavingPremiumStatus();

在此上下文中使用 IQueryable 有两个相关问题。第一个是可能以域对象关系的形式向客户端泄露实现细节,即违反德米特定律。第二个是存储库获得了查找可能不属于域对象存储库本身的职责,例如,查找与所请求的域对象相关而不是相关数据的投影。

此外,使用 IQueryable “打破”了这种模式:具有 IQueryable 的存储库可能会也可能不会提供对“域对象”的访问。 IQueryable 为客户端提供了很多关于最终执行查询时将具体化什么的选项。这是有关使用 IQueryable 的争论的主旨。

关于标量值,您不应使用存储库来返回标量值。如果您需要标量,通常可以从实体本身获取。如果这听起来效率低下,确实如此,但您可能不会注意到,具体取决于您的负载特征/要求。如果由于性能原因或需要合并来自多个域对象的数据而需要域对象的备用 View ,则有两种选择。

1) 使用实体的存储库查找指定的实体并将项目/映射到平面 View 。

2) 创建一个查找器界面,专门用于返回封装所需扁平 View 的新域类型。这不会是一个存储库,因为不会有集合语义,但它可能会在幕后使用现有的存储库。

如果您使用“纯”存储库来访问持久化实体,需要考虑的一件事是您会损害 ORM 的一些好处。在“纯”实现中,客户端无法提供如何使用域对象的上下文,因此您无法告诉存储库:“嘿,我只是要更改 customer.Name 属性,所以不要这样做”不必费心去获取那些急切的引用资料。另一方面,问题是客户是否应该了解这些东西。这是一把双刃剑。

就使用 IQueryable 而言,大多数人似乎都愿意“打破”模式以获得动态查询组合的好处,特别是对于分页/排序等客户端职责。在这种情况下,您可能会:

Add(T entity);
Remove(T entity);
T GetById(object id);
IQueryable<T> Find();

然后您可以取消所有这些自定义 Finder 方法,随着查询需求的增长,这些方法确实会使存储库变得困惑。

关于asp.net - 存储库模式最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1347687/

相关文章:

asp.net - 通过身份验证 - IIS 和 dotNet

c# - 在域和存储库之间共享实用程序对象

git - 像 CHANGELOG/LICENSE/VERSION/CONTRIBUTING/new_issue 这样的特殊文件叫什么?

android - 不同 Android 存储库之间的 repo merge

c# - 无法将 List<> 对象序列化/反序列化为 JSON

c# - ConnectionStrings 从哪里来? ASP.net

asp.net - 带有 IIS 6.0 和 .Net 4 的 Default.aspx?

java - 当重写 spring 存储库方法而不实现时会发生什么

asp.net-mvc - 存储库模式 : good or bad?

entity-framework - .net 如何使搜索方法不区分大小写?