为什么需要仓储呢?领域对象(一般是聚合根)的被创建出来后的到最后持久化到数据库都需要跟数据库打交道,这样我们就需要一个类似数据库访问层的东西来管理领域对象。那是不是我们就可以设计一个类似DAL层的东东来管理对象呢?是的,但是呢设计上有点区别,就是我们不希望上层如应用层直接访问数据,我们所有的操作应该是围绕着领域对象来的,所以我们还设计了仓储接口在领域层,然后把仓储的实现放在基础设施层。这样的设计模式很常见,一般用来解耦的。但是仓储不处理事务,事务处理我们一般交给UnitOfWork,有关于UnitOfWork的介绍大家可以参考下我之前一篇文章UnitOfWork以及其在ABP中的应用

ABP中设计仓储的思路,其实也很简单,就是提供领域对象的一些常用的数据库操作,一般的仓储存放的对象是聚合根,但是呢ABP没有严格区分聚合根,它简单的把所有的对象都当作聚合根,这样的设计也见于NOP中。下面我是画了ABP仓储设计的一张类图。

这个类图中我们可以清楚的看出几个:

1、仓储设计的意义,有人说我用EF开发DbSet<T>其实就是一个仓储的呀,我干嘛还需要重新定义一个Repository呢?答案在上图中体现的很明显,我们可能不确定以后我们的项目时候会用到其他数据库访问框架,比如NHibernate或MongoDb。那么如果我设计了IRepository这个接口后,我如果哪天我项目需要用到MongoDB了,那么我就可以继承IRepository实现一个MongoDbRepositoryBase类。

2、AbpRepositoryBase这个基类GetAll返回的是IQueryable<T>,但是呢IQueryable返回的是一个查询分析器,不是一个结果Model。这样我们就没办法确定这个GetAll到底是返回什么,就没有办法单元测试等。这个问题之前已经在蟋蟀博文Repository 返回 IQueryable?还是 IEnumerable?中讨论过了,有兴趣的同学可以参考下哈。一般的严格DDD是不能这个直接返回IQueryable的,但是如果你不是严格的DDD就无所谓了。为此我特地参考了下netfocus的ENode的案例forum,具体可以查看博文ENode简介与各种资源汇总(持续更新中。。。)下面我们来看下netfocus专家是怎么设计的吧。因为对forum还不是很熟悉,我只找到到账号索引仓储的设计。

namespace Forum.Domain.Accounts
{
/// <summary>
/// 账号索引信息的仓储接口,用于存储账号的唯一索引信息,实现账号名称的唯一性约束
/// </summary>
public interface IAccountIndexRepository
{
/// <summary>根据账号名称检索账号索引信息
/// </summary>
/// <param name="accountName"></param>
/// <returns></returns>
AccountIndex FindByAccountName(string accountName);
/// <summary>添加一个账号索引
/// </summary>
/// <param name="index"></param>
void Add(AccountIndex index);
}
}

接下来是基础设施层的实现方法

namespace Forum.Domain.Dapper
{
[Component]
public class AccountIndexRepository : IAccountIndexRepository
{
public AccountIndex FindByAccountName(string accountName)
{
using (var connection = GetConnection())
{
connection.Open();
var data = connection.QueryList(new { AccountName = accountName }, Constants.AccountIndexTable).SingleOrDefault();
if (data != null)
{
return new AccountIndex(data.AccountId as string, accountName);
}
return null;
}
}
public void Add(AccountIndex index)
{
using (var connection = GetConnection())
{
connection.Open();
connection.Insert(new
{
AccountId = index.AccountId,
AccountName = index.AccountName
}, Constants.AccountIndexTable);
}
} private SqlConnection GetConnection()
{
return new SqlConnection(ConfigSettings.ConnectionString);
}
}
}

从上面我们可以知道,它用的数据访问技术是Dapper,不是EF,它也没有IQueryable的设计,需要什么就查找什么比如FindByAccountName,这个就是严格按照DDD模式设计的仓储。这样的设计和ABP的设计各有优点,看项目需求吧。至此我的仓储也先总结到这里了,我还是DDD的初学者,可能有些理解不到位,希望相互学习共同成长。博客园已经有很多类似的文章了,这篇主要设计到ABP相关的,作为ABP的系列的一篇。

参考文章:

http://www.cnblogs.com/netfocus/archive/2011/10/10/2204949.html

http://www.cnblogs.com/xishuai/p/repository-return-iqueryable-or-ienumerable.html

http://www.cnblogs.com/jesse2013/p/ddd-repository.html

关于领域驱动设计(DDD)仓储的思考的更多相关文章

  1. 领域驱动设计(DDD)

    领域驱动设计(DDD)实现之路 2004年,当Eric Evans的那本<领域驱动设计——软件核心复杂性应对之道>(后文简称<领域驱动设计>)出版时,我还在念高中,接触到领域驱 ...

  2. 基于ABP落地领域驱动设计-03.仓储和规约最佳实践和原则

    目录 系列文章 仓储 仓储的通用原则 仓储中不包含领域逻辑 规约 在实体中使用规约 在仓储中使用规约 组合规约 学习帮助 围绕DDD和ABP Framework两个核心技术,后面还会陆续发布核心构件实 ...

  3. 领域驱动设计(DDD:Domain-Driven Design)

    领域驱动设计(DDD:Domain-Driven Design) Eric Evans的"Domain-Driven Design领域驱动设计"简称DDD,Evans DDD是一套 ...

  4. python 全栈开发,Day116(可迭代对象,type创建动态类,偏函数,面向对象的封装,获取外键数据,组合搜索,领域驱动设计(DDD))

    昨日内容回顾 1. 三个类 ChangeList,封装列表页面需要的所有数据. StarkConfig,生成URL和视图对应关系 + 默认配置 AdminSite,用于保存 数据库类 和 处理该类的对 ...

  5. 关于领域驱动设计 DDD(Domain-Driven Design)

    以下旨在 理解DDD. 1.     什么是领域? 妈妈好是做母婴新零售的产品,应该属于电商平台,那么电商平台就是一个领域. 同一个领域的系统都有相同的核心业务. eg: 电商领域都有:商品浏览.购物 ...

  6. 基于领域驱动设计(DDD)超轻量级快速开发架构(二)动态linq查询的实现方式

    -之动态查询,查询逻辑封装复用 基于领域驱动设计(DDD)超轻量级快速开发架构详细介绍请看 https://www.cnblogs.com/neozhu/p/13174234.html 需求 配合Ea ...

  7. 分享我对领域驱动设计(DDD)的学习成果

    本文内容提要: 1. 领域驱动设计之领域模型 2. 为什么建立一个领域模型是重要的 3. 领域通用语言(Ubiquitous Language) 4.将领域模型转换为代码实现的最佳实践 5. 领域建模 ...

  8. 我对领域驱动设计(DDD)的学习成果

    领域驱动设计之领域模型 2004年Eric Evans发表Domain-Driven Design – Tackling Complexity in the Heart of Software (领域 ...

  9. 领域驱动设计(DDD)实践之路(一)

    本文首发于 vivo互联网技术 微信公众号 链接: https://mp.weixin.qq.com/s/gk-Hb84Dt7JqBRVkMqM7Eg  作者:张文博 领域驱动设计(Domain Dr ...

  10. 领域驱动设计(DDD)实现之路

    2004年,当Eric Evans的那本<领域驱动设计——软件核心复杂性应对之道>(后文简称<领域驱动设计>)出版时,我还在念高中,接触到领域驱动设计(DDD)已经是8年后的事 ...

随机推荐

  1. [转载]JavaScript 中小数和大整数的精度丢失

    标题: JavaScript 中小数和大整数的精度丢失作者: Demon链接: http://demon.tw/copy-paste/javascript-precision.html版权: 本博客的 ...

  2. nc

    http://www.oschina.net/translate/nc-command-examples http://nixdoc.net/man-pages/openbsd/man1/nc.1.h ...

  3. C primer plus 练习题 第六章

    16. #include <stdio.h> int main() { double remain = 100.0; ; ) { remain = remain * 0.08 + rema ...

  4. mysql日期类型默认值'0000-00-00'容错处理

    mysql日期默认值'0000-00-00'惹的祸 .net连mysql数据库时,如果表里有字段是日期型且值是‘0000-00-00’时,会报错.在C#里面日期不可能是那样的.或许是最小日期定义的差别 ...

  5. Why is processing a sorted array faster than an unsorted array?

    这是我在逛 Stack Overflow 时遇见的一个高分问题:Why is processing a sorted array faster than an unsorted array?,我觉得这 ...

  6. SGU 422 Fast Typing(概率DP)

    题目大意 某人在打字机上打一个字符串,给出了他打每个字符出错的概率 q[i]. 打一个字符需要单位1的时间,删除一个字符也需要单位1的时间.在任意时刻,他可以花 t 的时间检查整个打出来的字符串,并且 ...

  7. js获取客户端计算机硬件及系统信息

    注意:(1):遇到“automation服务器不能创建对象”的问题 解决方案: 1.在“运行”中执行regsvr32 scrrun.dll 2.安全模式设置成“中”,如果javascript脚本中报这 ...

  8. Eclipse为Unity3d编写jar组件

    Unity3d和Android的交互有两种方式: (1)使用Eclipse为Unity3d编写库,也就是jar包,然后导入到U3D中使用: (2)将Unity3d项目导出为Android项目,然后直接 ...

  9. 自动化回归测试案例评价标准 MeRest

    自动化回归测试案例评价标准试图定义不同维度来评价自动化案例的优劣,作为后续我们评判讨论测试框架.测试技术和测试案例编写模式的基础.那什么是好的自动化回归测试案例呢?简而言之,就是投资回报率高的案例,因 ...

  10. SQL Server中的事务日志管理(4/9):简单恢复模式里的日志管理

    当一切正常时,没有必要特别留意什么是事务日志,它是如何工作的.你只要确保每个数据库都有正确的备份.当出现问题时,事务日志的理解对于采取修正操作是重要的,尤其在需要紧急恢复数据库到指定点时.这系列文章会 ...