这是关于我从这里找到的一些实体框架材料的一些混淆: 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。我想我错过了什么。我没有看到在这个实现中有任何协调......如果出现问题,事情如何“回滚”?
答案 0 :(得分:3)
不要使用其他UoW /存储库抽象层
正如OP正确指出的那样,实体框架(类似于NHibernate和其他ORM)已经为您提供了数据库的抽象,同时提供了可供您使用的事务“工作单元”和“存储库”。
额外的UoW /存储库抽象层是反模式,应该不惜一切代价避免。它有很多问题,其中最重要的是:
但是,但是......
我需要通过模拟我的存储库进行单元测试
不,你没有。只需使用具有针对您的测试的特定内容的数据库。如果您希望更快,请使用内存数据库(例如SQLite,Effort,...)。
不,你不应该。要在基础架构抽象层(例如工作单元或存储库)中实现业务逻辑,这是完全错误的。EF不强制执行未在数据关系中表达的业务逻辑...要强制执行此类逻辑,您必须在EF上下文中构建一个OUW / Repository /。
null
,x
和y
之间的值)不会:那些应该在您的系统接口边界解决。 另请注意,没有任何有价值的业务逻辑的简单 CRUD 样式操作不需要经历所有“层箍”,即避免这种模式:
直接从控制器中的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 /。这是你知道的唯一原因。