我实际上不同意EF 是“存储库模式”的正确示例。它是一个类型化的数据访问层和一个公开的 LINQ 实现。
请注意,如果完全认可 EF 为“业务领域”,则上述内容不成立;但是,我将 EF 与 Schema First 一起使用 - 和它一样糟糕 - 在 Schema First 中,EF不是严格的业务领域。“正确”一词用于强化这一观点——根据您自己的观点/设计进行调整。
在我的书中,正确的存储库模式暴露了相关操作的聚合根。也就是说,实现细节(EF)尽可能地保存在存储库中。也就是说,存储库负责将相关域对象映射到底层模型。
这是与 Microsoft 如何定义存储库模式的协议- 请注意,业务实体映射到数据源。(因此,我对 EF 履行这个角色的根本分歧:EF只有在从 Code First 设计时才有机会理智地映射业务实体。)
我发现的最好的总结/文章是存储库模式,由 Gauffin 完成。虽然他从比我更极端的角度来处理存储库模式,但这里有一些关键点可以解释为什么 EF 会简单地通过 Active Record / ORM 模式流血。
以下是一些精选的摘录,强调了为什么我不认为 EF 是存储库模式的正确实现。
存储库模式是一种抽象。它的目的是降低复杂性并使其余代码持久无知。作为奖励,它允许您编写单元测试而不是集成测试。问题是许多开发人员未能理解模式的目的 - 并创建存储库 [即。EF] 将持久性特定信息泄露给调用者
..
使用存储库并不是为了能够切换持久性技术(即更改数据库或使用 Web 服务等)。存储库模式确实允许您这样做,但这不是主要目的。
..
当人们谈论存储库模式和单元测试时,他们并不是说该模式允许您对数据访问层使用单元测试。如果您在业务逻辑中使用 ORM/LINQ,您将永远无法确定测试失败的原因。
..
请注意,存储库模式仅在您拥有首先使用代码映射的 POCO 时才有用。否则,您只会使用实体破坏抽象。[也就是说,只有 EF Code First 甚至可以尝试满足这个要求。]
..
构建正确的存储库实现非常容易。事实上,您只需要遵循一条规则:在您需要之前不要将任何内容添加到存储库类中
如果您确实使用 EF 作为存储库 - 我相信它仍然是一个类型化的 DAL,尽管它会流血 - 请不要试图将它隐藏在“更通用”的模式中 - 存储库模式与类型统一无关,它是关于公开特定上下文的聚合根以及对此类的操作。
请参阅存储库模式解决了哪些具体问题?也是。
虽然我反对EF 是一个正确的存储库模式——它是 Active Record 模式——但我不是一个存储库纯粹主义者。也就是说,在某些情况下,我会在特定情况下流血 EF(或 L2S)实体;我接受这是技术债务。只需了解打破此类存储库/域边界的成本即可。