【问题标题】:UOW and Repository Pattern in EF5EF5 中的 UOW 和存储库模式
【发布时间】:2015-04-30 15:56:16
【问题描述】:

这是关于我从这里找到的一些实体框架材料的一些困惑: https://www.asp.net/

在此页面上,它解释了如何使用存储库包装 dbcontext 以及使用工作单元类包装存储库: http://www.asp.net/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application

但是,在此页面上,它声明 dbcontext 已经是 UOW 模式和存储库模式的组合: https://msdn.microsoft.com/en-us/library/system.data.entity.dbcontext(v=vs.103).aspx

那么如果这些模式解决的问题已经被 dbcontext 解决了,为什么要使用 EF5 重新实现这些模式呢?

此外,在本教程中,UnitOfWork 类似乎没有显示出 UOW 应该提供的任何好处。例如,它声明:“这样,当一个工作单元完成时,您可以在该上下文实例上调用 SaveChanges 方法,并确保所有相关更改都将得到协调。”

但它似乎所做的只是无缘无故地包装 dbcontext。我想我错过了一些东西。我在这个实现中看不到任何协调......如果出现问题,如何“回滚”?

【问题讨论】:

  • 每次我看到“工作单元”或“存储库”与“实体框架”标签相结合的问题时,我都想知道同样的事情。我会看这个...+1
  • @spender 是的,有趣的是,有多少人试图在已经为他们抽象数据库的东西上添加另一个抽象层。我不相信 OP 在这个question 非常感谢我的answer。我也会感兴趣地关注这个问题。

标签: c# asp.net-mvc entity-framework-5


【解决方案1】:

不要使用另一个 UoW/存储库抽象层

正如 OP 正确指出的那样,实体框架(类似于 NHibernate 和其他 ORM)已经为您提供了数据库的抽象,其中包含可供您使用的事务性“工作单元”和“存储库”。

额外的 UoW / 存储库抽象层是一种反模式,应该不惜一切代价避免。它存在许多问题,其中最重要的是:

  • 它们会阻止您使用底层 ORM 的全部功能(延迟加载、急切加载、复杂查询......)
  • 如果他们想提供除了简单的 CRUD 之外的任何附加好处,他们将是有漏洞的(即反映底层 ORM 中存在的功能)。

但是,但是,但是……

我需要能够通过模拟我的存储库来进行单元测试

不,你没有。只需使用具有特定于您的测试内容的数据库即可。如果您希望它更快,请使用内存数据库(例如 SQLite、Effort、...)。

EF 不强制执行未在数据关系中表达的业务逻辑...要强制执行这种类型的逻辑,您必须围绕 EF 上下文构建某种类型的 OUW/Repository/both。

不,你不应该。在基础设施抽象层(例如工作单元或存储库)中实现业务逻辑是完全错误的。

  • 有价值的业务逻辑属于领域实体、领域服务、领域命令或长期运行的业务流程、sagas。
  • 简单验证(即不是nullxy 之间的值)不要:这些应该在您的系统接口边界处解决。

另请注意,没有任何有价值的业务逻辑的简单 CRUD 样式操作不需要经过所有“层箍”,即避免这种模式:

  1. 数据库 → 没有行为的实体 → DTO → 视图模型 → 视图
  2. 编辑字段
  3. 视图 → 视图模型 → DTO → 没有行为的实体 → 数据库

只需直接从控制器中的 ORM 以视图所需的“视图模型”形状加载它,然后直接从控制器中保存。

关于抽象

诸如此类的不必要的抽象和层箍是邪恶的。它们会混淆您的代码、束缚您的手脚、泄漏、增加代码大小并因此增加代码中的错误数量,而不会提供任何附加值。

当它们为您提供附加值时使用抽象,例如当您需要他们解决横切关注点、捕捉/管理架构中的重复模式时,...

为了抽象而创建抽象是浪费时间。

【讨论】:

    【解决方案2】:

    我已经在此here 上写了很多文章,但为了您的利益,我会总结一下。是的,Entity Framework 已经实现了 UoW (DbContext) 和存储库 (DbSet) 模式。再次重新实现它们没有任何好处。事实上,这会带来很大的不利影响,因为它会显着增加项目的维护开销。

    为什么 Microsoft 在介绍性教程中包含此内容?老实说,我不确定,但这是一个困扰无数新 MVC 开发人员的错误,包括我刚开始的时候。

    某种抽象是有好处的,这样您的项目就不会依赖于任何一种特定的获取数据的方式。但是,此抽象应该返回您的操作所需的特定数据,不多也不少。由于没有更好的词,我将其称为“服务”,尽管 Microsoft 通过 SOA 为该词赋予了完全不同的含义。简单地说,就像您只是在为您的应用程序创建一个 API 以供使用,就像您在创建一个 Web API 一样,只是完全基于代码(不需要实际的 HTTP 连接)。然后它会进入您的项目可以引用的 DAL 层(类库或类似的)。

    【讨论】:

      【解决方案3】:

      关于 EF 的问题在于它公开的 OUW 或存储库功能中没有业务逻辑。如果您调用 SaveChanges,它会很高兴地保存所有更改。但是,有一个要求是,当添加一个 Widget 时,必须为 Widget 添加一个 Frobber,否则您很不走运(除非涉及 FK 依赖项)。对于任何未在数据关系中表达的业务逻辑,EF 开箱即用不会强制执行。

      要强制执行这种类型的逻辑,您必须围绕 EF 上下文构建某种类型的 OUW/Repository/both。据我所知,这是你这样做的唯一原因。

      【讨论】:

        【解决方案4】:

        工作单元和存储库模式与实体框架无关。它是设计模式之一。因此它用于使您的代码更具可读性、可重用性和高效性,并且这些模式用于实现单次对象实例化(一次性对象实例化)以及避免控制反转。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-09-04
          • 1970-01-01
          • 2020-06-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-02-05
          相关资源
          最近更新 更多