EF5中的UOW和存储库模式

时间:2015-04-30 15:56:16

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

这是关于我从这里找到的一些实体框架材料的一些混淆: 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。我想我错过了什么。我没有看到在这个实现中有任何协调......如果出现问题,事情如何“回滚”?

3 个答案:

答案 0 :(得分:3)

不要使用其他UoW /存储库抽象层

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

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

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

但是,但是......

  

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

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

  

EF不强制执行未在数据关系中表达的业务逻辑...要强制执行此类逻辑,您必须在EF上下文中构建一个OUW / Repository /。

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

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

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

  1. 数据库→无行为的实体→DTO→查看模型→查看
  2. 修改字段
  3. 查看→查看模型→DTO→无行为的实体→数据库
  4. 直接从控制器中的ORM以视图所需的“视图模型”形状加载它,并直接从控制器中保存。

    关于抽象

    这些不必要的抽象和层层箍是邪恶的。它们会混淆您的代码,绑定您的手,泄漏,增加代码大小,从而增加代码中的错误数量,而不会提供任何附加价值。

    当它们为您提供附加值时使用抽象,例如当您需要他们解决跨领域问题,捕获/管理您的架构中的重复模式时,......

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

答案 1 :(得分:2)

我已经就此here撰写了大量文章,但我会总结一下您的利益。是的,实体框架已经实现了UoW(DbContext)和存储库(DbSet)模式。重新实施它们没有任何好处。实际上,这会给您的项目的维护开销带来很大的不利影响。

为什么Microsoft在入门教程中包含了这个?老实说,我不确定,但这是一个困扰无数新MVC开发人员的错误,当我刚开始时,我自己也包括在内。

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

答案 2 :(得分:0)

关于EF的事情是它暴露的OUW或Repository功能中没有业务逻辑。如果您调用SaveChanges,它将很乐意保存所有更改。但是,有一个要求是,当添加说Widget时,为Widget添加Frobber是必要的,你运气不好(除非涉及到FK依赖)。对于未在数据关系中表达的任何业务逻辑,开箱即用的EF不会强制执行它。

要强制执行此类逻辑,您必须围绕EF上下文构建某种OUW / Repository /。这是你知道的唯一原因。