24

我正在使用 EF 4.1 Code First 布局一个新的数据层,从旧的自制数据层迁移。

我设置了两个程序集,一个用于我的上下文,一个用于所有 POCO 代码第一类。

我有一些业务逻辑,例如,针对在几个不同地方使用的一个表(或几个表)的查询。 我应该把它放在哪里?

它不能进入​​ POCO 类,因为它连接了几个表,因此需要一个上下文。它可以在上下文中进行,但是该上下文会因数百个杂乱无章的查询而变得臃肿。 所有业务逻辑是否有共同的模式或安排?

4

3 回答 3

76

看起来存储库模式可以解决所有问题……存储库不是灵丹妙药!

我每天都在 EF 中使用存储库模式,因为几个月前我开始当前项目时,它看起来像是推荐的解决方案。我的结论:

  • 存储库使与 EF 的交互变得更加困难。只需浏览与 EF 标签相关的问题,您就会看到必须直接在 context、changetracker 等上处理哪些复杂性。
  • 通用存储库适用于 CRUD 操作,但不适用于真正的 DDD 场景。一旦您的存储库与聚合根 (DDD) 一起使用,通用方法就会失败。
  • 单元测试根本不起作用,因为一旦暴露IQueryable. Linq-to-entities 只是 Linq-to-objects 的子集,mock 不处理引用完整性,所以我多次看到绿色单元测试和运行时异常。使用 EF 的正确测试方法是集成测试。模拟存储库仅用于测试与数据访问无关的真实业务逻辑。如果您没有对访问或持久化数据的业务方法进行集成测试,则您没有对其进行测试。
  • 公开像 GetByXXX 这样的特殊方法只是后退一步。大多数这些方法只使用一次。您将以类似于用于包装存储过程调用的存储库的代码结束。许多开发人员喜欢 ORM 只是因为他们可以避免这种死板的架构。

EF 本身已经提供存储库模式 -DbSet并且ObjectSet是存储库并且DbContextObjectContext工作单元。所以在我看来,存储库模式被过度使用了。它在需要严格分层的大型项目或在其方法中放置额外逻辑的情况下很有用。仅仅因为您想包装对 EF 的访问而使用存储库通常是无价值的代码,而且只是增加了一层复杂性。

您可以以同样的方式创建定义查询的可重用方法。

于 2011-03-30T16:06:54.180 回答
4

我会使用存储库模式。这是一个使用 EF 代码优先和 MVC Entity Framework 4 CTP 4 / CTP 5 Generic Repository Pattern 和 Unit Testable的示例

这里有一些关于模式的好读物:

由于您是从领域模型开始的,因此研究领域驱动设计 (DDD) 可能也是一个好主意。

一些关于 DDD 的好读物:

于 2011-03-30T15:31:22.870 回答
2

如果您在业务方法(领域层服务和应用层服务)中直接使用 EF,那么您并没有将领域模型层与基础设施技术(在本例中为 EF)隔离开来。这是 DDD 原则之一。每个聚合可能应该有一个存储库。

有关 DDD 的更多信息,请参阅:

Eric Evans 的书: http ://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215

微软:http: //msdn.microsoft.com/es-es/architecture/en

于 2011-05-23T14:13:12.287 回答