【问题标题】:Getting Started with Repository Pattern存储库模式入门
【发布时间】:2010-07-23 15:01:57
【问题描述】:

我正在尝试开始使用存储库模式和 ASP.NET MVC,但我不禁相信我遗漏了一些东西。如果这是一个愚蠢的问题,请原谅我,但在我看来,实现会以指数方式违反 DRY。例如,在我(诚然是新手)的理解中,为了实现这一点,我必须:

  1. 创建我的数据库模型(目前使用 Linq to Sql)
  2. 为每个概念(表或相关表组)创建一个 IRepository
  3. 为每个 IRepository 创建一个实现
  4. 我们返回 L2S 对象还是某种 DTO?
  5. 创建作为容器或数据副本的视图模型
  6. 在控制器上使用某种 DI 方法(Windsor 还是 Unity?)

虽然我意识到可扩展性和可移植性是有代价的,但感觉就像我错过了什么?

【问题讨论】:

  • 您可以创建一个通用存储库,并简单地实现您需要的特定...
  • 您可能想查看 MVC 或 BlogEngine.NET 的 Ninject 网站源代码(在 Nate Kohari 的 Github 上),它在 ASP.NET WebForms 中实现了存储库模式(实际上 Mads 将它实现为类库,所以它当您没有控制器和视图等所有 MVC 东西时更容易理解)。

标签: asp.net-mvc repository-pattern


【解决方案1】:

我尝试在 LINQ 2 SQL 中实现存储库模式,但效果不佳,主要是因为 L2S 不使用 POCO,并且您必须始终映射到 DTO,正如您提到的那样。虽然您可以使用 AutoMapper 之类的东西,但 L2S 并不是非常适合存储库模式。

如果您打算使用存储库模式(我会推荐它),请尝试不同的数据访问技术,例如 NHibernate 或 Entity Framework 4.0 的 POCO 支持。

此外,您不会为每个表创建一个存储库,而是为每个 域聚合 创建一个存储库,并使用存储库仅访问聚合的 Root 实体.例如,如果您有一个电子商务应用程序,其中包含 OrderOrderItem 实体,则一个 Order 具有一个或多个 OrderItem。这两个实体是单个聚合的一部分,Order 实体是聚合根。在这种情况下,您只会创建一个 OrderRepository,而不是 OrderItemRepository。如果您想添加新的 OrderItem,您可以通过获取对 Order 实体的引用,然后将新的 OrderItem 添加到 Order 的 Items 集合中,然后使用您的 OrderRepository 保存 Order。这种技术称为DomainDrivenDesign,如果您的应用程序中有复杂的域模型和业务规则,它是一个非常强大的范例。但是在简单的应用程序中它可能会被杀死,所以你必须问问自己你的领域模型的复杂性是否需要使用这种方法。

就坚持 DRY 而言,通常我创建一个基础 Repository 类,该类具有 Save、Delete、FetchById 等常用方法。只要我的 Repository 类实现了这个基类(OrderRepository、ProductRepository 等),他们就可以免费获得这些方法,并且代码是 DRY。由于 POCO 支持,这在 NHibernate 中很容易做到,但在 Linq 2 SQL 中则不可能。

不要太担心将您的领域模型直接发送到视图,大多数专用视图模型看起来几乎与领域模型相同,所以重点是什么。尽管出于安全问题,我倾向于避免使用 DM 将数据发回服务器。

如果您遵循这种 POCO 方法(并且放弃 LINQ 2 SQL,老实说!!),您最终只会得到一个类(您的 POCO 实体)而不是 3 个(L2S 类、DTO 和 ViewModel)。

Repository Pattern 的实现可能很糟糕,所以要小心行事,阅读一些教程,博客文章书籍等。(我推荐Steven Sanderson's book,特别是看先决条件章节)但是一旦掌握,它就变成了一种非常强大的方式来组织将模型对象与数据存储之间的水合复杂性。如果您使用 Repository 接口(IOrderRepository 等)并通过 IOC 容器注入它们,您还可以获得可维护性和单元可测试性的好处。

【讨论】:

  • 我曾经在 Views 中使用我的域模型类,它工作正常,但当我不得不制作自定义活页夹、特殊扩展等时,我一直遇到问题。 XML/SQL DB 所以我决定创建另一组 ViewModel 类,是的,它们看起来几乎相同,但并不完全相同。您可以更轻松地调整 ViewModel 类,并使它们更适用于 View 的需求。然后我使用 ValueInjector(新的很棒的工具,比 Automapper 更好)来同步 ViewModel 和 Model 实例。
  • 我想你会发现 LINQ2SQL 确实支持 POCO,它只需要你向 POCO 类添加属性以进行映射。除非您获得 CTP,否则 EF4 不支持此功能,然后它仅支持与 L2S 相同程度的 POCO。 Steve 之所以选择 L2S 来写他的书,部分原因在于 POCO 的支持。如果您想分离 POCO 以与数据实现无关,您可以将属性设为虚拟并在依赖于您的数据实现的派生类中覆盖它们。甚至 NHibernate 都要求您将属性设为虚拟(延迟加载)
【解决方案2】:

您是否了解您为什么要做这些事情,或者您只是在关注博客文章或其他来源?

不要实施存储库模式,因为它是新的热点。实施它是因为您了解这些关注点分离如何帮助您的项目和代码的整体质量。

从您的问题中的 ? 看来,您在实施之前需要做更多的阅读。您可能缺少对整体架构方法的有意义的理解。请不要采取错误的方式,我不想消极。

侧面咆哮:

显然,最新的存储库热度图片中缺少某些内容,因为对实现细节的混淆,例如单个存储库与许多/分组的“DTO 或不 DTO”是如此模棱两可和主观的。这是一个反复出现的“小问题”。

【讨论】:

  • 一般来说,我的理由是因为我不想让 LINQ 代码支配我的控制器。它将把项目变成一个无法维护的烂摊子。此外,似乎所有文章都将存储库“热度”作为分层设计、测试、抽象和世界饥饿的灵丹妙药。你的帖子没有冒犯,因为我试图收集对系统的“有意义的理解”。
  • LINQ 代码通常不应出现在您的控制器中。您的控制器应该依赖于存储库(接口)的抽象,以便调用方法来获取数据。存储库的实现应该处理数据访问。
  • @Matt Murrell 你以前在控制器中使用过 LINQ 吗?
  • @马特。您经常会看到具有这种结构的帖子,就像您在 WebForms 的代码隐藏页面中看到的一样。 不是很好的设计,但方便炫耀功能。
【解决方案3】:

这个问题之前已经提出过,乍一看,正确分离关注点的某些方面确实违反了 DRY。

正如您提到的 MVC,您是否阅读过 Steve Sanderson 的 Pro ASP.NET MVC 2 Framework 书?它花费了大量时间来解释为什么使用存储库模式是一个好主意。

您可能会发现,对于您正在从事的项目,它不合适,没关系。不要使用它,看看您是否遇到了本可以解决的问题。您无需成为一名开发人员就可以意识到保持应用程序的不同部分尽可能松散耦合是多么重要。

【讨论】:

  • + 1 到 Steven Sanderson 的书,这是 ASP.NET MVC 恕我直言的最佳书籍,它很好地解释了 Repository + DDD。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多