实体框架作为存储库和UnitOfWork?

时间:2009-02-06 12:09:05

标签: entity-framework domain-driven-design

我正在开始一个新项目,并决定尝试合并DDD模式,还包括Linq to Entities。当我查看EF的ObjectContext时,它似乎正在执行Repository和Unit of Work模式的功能:

存储库的意思是底层数据级接口是从实体表示中抽象出来的,我可以通过ObjectContext请求和保存数据。

工作单元,我可以将所有插入/更新写入objectContext并在执行SaveChanges()时一次性执行它们。

将这些模式的另一层放在EF ObjectContext之上似乎是多余的?似乎Model类可以使用'partial class'直接合并到EF生成的实体之上。

我是DDD的新手,所以如果我在这里遗漏了什么,请告诉我。

3 个答案:

答案 0 :(得分:17)

我认为实体框架不是Repository的良好实现,因为:

  • 对象上下文不够抽象,不能对引用它的事物进行良好的单元测试,因为它绑定到DB访问。相反,使用IRepository引用可以更好地创建单元测试。
  • 当客户端可以访问ObjectContext时,客户端可以执行它所关心的任何事情。对此完全唯一的真正控制是将某些类型或属性设为私有。以这种方式很难实现良好的数据安全性。
  • 在一个非平凡的模型上,ObjectContext不够抽象。例如,您可以将表和存储过程映射到同一实体类型。您并不希望客户端必须区分这两个映射。
  • 在相关的说明中,很难编写全面且执行良好的业务规则和实体代码。实际上,无论这是否是一个好主意都值得商榷。

另一方面,一旦有了ObjectContext,实现Repository模式就变得微不足道了。实际上,对于不是特别复杂的情况,Repository是ObjectContext和Entity类型的包装器。

答案 1 :(得分:7)

我想说你应该把ObjectContext看作你的UnitOfWork,而不是作为一个存储库。

ObjectContext不能是存储库-imho-因为它是'泛型'。 您应该创建自己的存储库,它们在常规CRUD方法旁边有专门的方法(例如GetCustomersWithGoldStatus)。

所以,我要做的是创建存储库(每个聚合根一个),让这些存储库使用ObjectContext。

答案 2 :(得分:0)

我喜欢拥有存储库层,原因如下:

EF gotcha's

当你看一些关于EF(Code First版本)的当前教程时,显然有许多问题需要处理,特别是在对象图(包含实体的实体)和断开连接的场景之间。我认为存储库层非常适合将它们包装在一个地方。

数据访问机制的清晰画面

存储库提供有关BL如何访问和更新数据存储的特​​定图片。它公开了具有明确单一目的的方法,并且可以独立于BL进行测试。来自教科书的标准示例,查找()来查找单个实体。一个更具特定于应用程序的示例,清除()以清除数据库表。

优化的地方

使用香草EF时,你不可避免地会遇到性能问题。我使用存储库来隐藏BL的优化机制。

示例,

GetKeys()从表中投影缓存的密钥(用于插入/更新决策)。只读密钥比读取完整实体更快,占用的内存更少。

通过SqlBulkCopy批量加载。 EF将通过单个SQL语句插入。如果您希望单个语句插入多行,SqlBulkCopy是一个很好的机制。存储库封装了它并为SqlBulkCopy提供了元数据。除了Insert方法之外,还需要一个StartBatch()和EndBatch()方法,它也是UnitOfWork层的参数。