Dav*_*ave 43 design-patterns domain-driven-design entity-framework repository-pattern
(注意:我的问题与三个月前提出这个问题的人非常相似,但从未得到过回答.)
我最近开始使用MVC3 + Entity Framework,我一直在阅读最佳实践是使用存储库模式集中访问DAL.这也伴随着您希望将DAL与域(尤其是视图层)分开的解释.但是在示例中,我看到存储库(或似乎是)只是返回DAL实体,即在我的情况下,存储库将返回EF实体.
所以我的问题是,如果它只返回DAL实体,那么存储库有什么用呢?这是否会增加一层复杂性,而不会消除在层之间传递DAL实体的问题?如果存储库模式创建"进入DAL的单一入口点",那么它与上下文对象有何不同?如果存储库提供了一种检索和持久化DAL对象的机制,那么它与上下文对象有何不同?
此外,我至少读过一个地方,工作单元模式集中了存储库访问以管理数据上下文对象,但我不知道为什么这也很重要.
我98.8%肯定我在这里遗漏了一些东西,但从我的读数中我没有看到它.当然,我可能只是没有阅读正确的消息来源......:
Eri*_*ing 52
我认为术语"存储库"通常被认为是由Martin Fowler 的"企业应用程序架构模式 "一书描述的" 存储库模式 " .
存储库在域和数据映射层之间进行调解,其作用类似于内存中的域对象集合.客户端对象以声明方式构造查询规范,并将它们提交给Repository以满足要求.可以从简单的对象集合中向对象添加对象或从对象库中删除对象,并且由存储库封装的映射代码将在后台执行适当的操作.
从表面上看,Entity Framework完成了所有这些,并且可以用作存储库的简单形式.但是,存储库可能不仅仅是数据层抽象.
根据Eric Evans的Domain Driven Design一书,存储库具有以下优势:
- 它们为客户提供了一个简单的模型,用于获取持久性对象和管理其生命周期
- 它们将应用程序和域设计与持久性技术,多个数据库策略甚至多个数据源分离
- 他们传达有关对象访问的设计决策
- 它们允许轻松替换虚拟实现,进行单元测试(通常使用内存中的集合).
第一点大致等同于上面的段落,很容易看出实体框架本身很容易实现它.
有人会争辩说EF也完成了第二点.但通常EF仅用于将每个数据库表转换为EF实体,并将其传递给UI.它可能是抽象数据访问机制,但它几乎没有抽象出幕后的关系数据结构.
在主要面向数据的简单应用程序中,这似乎不是一个重要的观点.但随着应用程序的域规则/业务逻辑变得更加复杂,您可能希望更加面向对象.数据的关系结构包含对业务域不重要的特性,但是数据存储的副作用并不罕见.在这种情况下,抽象持久性机制以及数据结构本身的性质是不够的.单独的EF通常不会帮助您这样做,但存储库层将.
至于第三个优势,EF将不做任何事情(从DDD的角度来看)来提供帮助.通常,DDD使用存储库不仅可以抽象数据持久性机制,还可以提供有关如何访问某些数据的约束:
对于通过遍历查找更方便的持久对象,我们也不需要查询访问权限.例如,可以从Person对象请求人员的地址.最重要的是,除了从根遍历之外,禁止访问AGGREGATE内部的任何对象.
换句话说,只是因为数据库中有一个Address表,就不会有'AddressRepository'.如果您的设计选择以这种方式管理Address对象的访问方式,那么您可以在PersonRepository中定义和强制执行设计选择.
此外,DDD存储库通常是封装与域数据集相关的某些业务概念的位置.OrderRepository可能有一个名为OutstandingOrdersForAccount的方法,它返回Orders的特定子集.或者Customer存储库可能包含PreferredCustomerByPostalCode方法.
如果没有添加存储库抽象层,实体框架的DataContext类就无法很好地适应这种功能.它们可以很好地用于DDD调用规范,它可以是简单的布尔表达式,发送到一个简单的方法,它将根据表达式计算数据并返回匹配.
至于第四个优点,虽然我确信某些策略可能让一个人替换datacontext,但将它包装在一个存储库中会让它变得简单.
关于"工作单元",这是DDD书中所说的内容:
将事务控制留给客户端.虽然REPOSITORY将插入数据库并从数据库中删除,但它通常不会提交任何内容.例如,在保存之后提交是很诱人的,但是客户端可能具有正确启动和提交工作单元的上下文.如果REPOSITORY保持不动,交易管理将更加简单.
Den*_*aub 22
实体框架DbContext基本上类似于存储库(以及工作单元).在简单的场景中,您不一定要抽象它.
存储库的主要优点是您的域可以是无知的并且独立于持久性机制.在基于层的体系结构中,依赖关系从UI层向下指向域(或通常称为业务逻辑层)到数据访问层.这意味着UI依赖于BLL,BLL本身依赖于DAL.
在更现代的架构中(由域驱动设计和其他面向对象的方法传播),域应该没有向外的依赖关系.这意味着UI,持久性机制和其他一切应该依赖于域,而不是相反.
然后,存储库将通过其域内的接口表示,但在域外的具体实现中,在持久性模块中.这种方式域只依赖于抽象接口,而不是具体实现.
这基本上是面向对象与体系结构上的过程编程.
另请参见端口和适配器(即六边形体系结构).
存储库的另一个优点是您可以为各种数据源创建类似的访问机制.不仅是数据库,还有基于云的商店,外部API,第三方应用程序等.
你是对的,在这些简单的情况下,存储库只是DAO的另一个名称,它只带来一个值:事实上你可以将EF切换到另一种数据访问技术.今天你正在使用MSSQL,明天你会想要一个云存储.或者使用micro orm而不是EF或从MSSQL切换到MySql.
在所有这些情况下,使用存储库是件好事,因为应用程序的其余部分将不关心您现在使用的存储.
还有一个有限的情况,你从多个来源(db +文件系统)获取信息,一个repo将充当外观,但它仍然是DAO的另一个名称.
"真实"存储库仅在您处理域/业务对象时才有效,对于不会更改存储的以数据为中心的应用程序,单独使用ORM就足够了.