(DDD)仓储的思考

为什么需要仓储呢?领域对象(一般是聚合根)的被创建出来后的到最后持久化到数据库都需要跟数据库打交道,这样我们就需要一个类似数据库访问层的东西来管理领域对象。那是不是我们就可以设计一个类似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还不是很熟悉,我只找到到账号索引仓储的设计。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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);
    }
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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)仓储的思考

    为什么需要仓储呢?领域对象(一般是聚合根)的被创建出来后的到最后持久化到数据库都需要跟数据库打交道,这样我们就需要一个类似数据库访问层的东西来管理领域对象.那是不是我们就可以设计一个类似DAL层的东东 ...

  2. 前端DDD总结与思考

    软件开发架构演化与DDD起源 单体服务架构:大概10年前,我在武汉工作的时候,甲方客户购买我们的产品,一般都是连着设备一起购买,一套软件系统,一台惠普或者戴尔的企业级服务器,再加一个黑色的铁盒,销售部 ...

  3. DDD的思考

    概述 DDD领域驱动设计,它是对面向对象的的分析和设计(OOAD,Object Orient Analysis Design)的一个补充,对技术框架进行了分层规划,同时对每个类进行了策略和类型划分.领 ...

  4. 对结合BDD进行DDD开发的一点思考和整理

    引言 二十年前的我,还在学校里抱着一台DIY机(德州486+大众主板+16M内存+3.5inch软驱+昆腾320M硬盘,当时全校最快主机没有之一),揣着一本<Undocumented DOS&g ...

  5. (原创)通用查询实现方案(可用于DDD)[附源码] -- 简介

    [声明] 写作不易,转载请注明出处(http://www.cnblogs.com/wiseant/p/3985353.html).   [系列文章] 通用查询实现方案(可用于DDD)[附源码] -- ...

  6. 通用查询实现方案(可用于DDD)[附源码] -- 简介

    原文:通用查询实现方案(可用于DDD)[附源码] -- 简介 [声明] 写作不易,转载请注明出处(http://www.cnblogs.com/wiseant/p/3985353.html).   [ ...

  7. 吉特仓库管理系统-ORM框架的使用

    最近在园子里面连续看到几篇关于ORM的文章,其中有两个印象比较深刻<<SqliteSugar>>,另外一篇文章是<<我的开发框架之ORM框架>>, 第一 ...

  8. DDD 领域驱动设计-三个问题思考实体和值对象(续)

    上一篇:DDD 领域驱动设计-三个问题思考实体和值对象 说实话,整理现在这一篇博文的想法,在上一篇发布出来的时候就有了,但到现在才动起笔来,而且写之前又反复读了上一篇博文的内容及评论,然后去收集资料, ...

  9. C#进阶系列——DDD领域驱动设计初探(二):仓储Repository(上)

    前言:上篇介绍了DDD设计Demo里面的聚合划分以及实体和聚合根的设计,这章继续来说说DDD里面最具争议的话题之一的仓储Repository,为什么Repository会有这么大的争议,博主认为主要原 ...

随机推荐

  1. 编程算法 - 不用加减乘除做加法 代码(C)

    不用加减乘除做加法 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 写一个函数, 求两个整数之和, 要求在函数体内不得使用+, -, *, /四 ...

  2. Steps UVA 846

    说说:此题要求求出从整数x到达整数y所要经过的最短步数,且第一步和最后一步必须为一,同一时候每一步都比前一步多一步,少一步或一样.如果想搞清楚每一步详细是如何走的,那么这道题是相当麻烦的.考虑到前后两 ...

  3. iframe属性參数

    iframe属性參数 当点击一个子页面的链接时, 怎样将还有一个子页面嵌入到当前iframe中 仅仅要给这个iframe命名就能够了. <iframe width=420 height=330 ...

  4. FusionCharts简单教程---建立第一个FusionCharts图形

    由于项目需求需要做一个报表,选择FusionCharts作为工具使用.由于以前没有接触过报表,网上也没有比较详细的fusionCharts教程,所以决定好好研究FusionCharts,同时做一个比较 ...

  5. cocos2d-x V3.0 呼叫加速度计 Acceleration

    今天克服了一个问题,我觉得非常酷 哈哈. 今天得到解决cocos2d-x 3.0 呼叫重力加速器问题,上网查了很多资料 发现是不够,不解决这个问题,我不知道如果我使用3.0 这一问题的版本号,但是,这 ...

  6. XMPP我写底层协议(零)--废话和准备开幕前

    当我想写一个非常早期的一点总结.但总是忙没有时间停止做这样的事情. 秦与我的兄弟之前说的,这并不是说我没开灵.但是,因为很多事情还没有时间来写blog. 我没有完全理解,真到自己在这个位置上的时间,能 ...

  7. Windows 7下一个:该应用程序不能正常启动(0xc0150002)

             在新系统中正确安装QQ2010无法执行,同一时候安装的TM2009也无法执行. 相同显示为"应用程序无法正常启动(0xc0150002). 请单击"确定" ...

  8. Mahout推荐算法ItemBased

    Mahout推荐的ItemBased 一.   算法原理 (一)    基本的 下面的例子,参见图评分矩阵:表现user,归类为item. 图(1) 该算法的原理: 1.  计算Item之间的相似度. ...

  9. Java中动态代理技术生成的类与原始类的区别

    用动态代理的时候,对它新生成的类长什么样子感到好奇.有幸通过一些资料消除了心里的疑惑. 平时工作使用的Spring框架里面有一个AOP(面向切面)的机制,只知道它是把类重新生成了一遍,在切面上加上了后 ...

  10. 局部敏感哈希(Locality-Sensitive Hashing, LSH)方法介绍

    局部敏感哈希(Locality-Sensitive Hashing, LSH)方法介绍 本文主要介绍一种用于海量高维数据的近似近期邻高速查找技术--局部敏感哈希(Locality-Sensitive ...