一直以来想自己做一套开发框架,在其基础上进行快速开发,自从接触微软的MVC框架和Entityframework以来,阅读了大量园子里的相关的技术文章,也进行了不少摸索和尝试,中间经历了多次大刀阔斧的重构,现在总算有了雏形,把权限、模式和界面初步搞定,但是回头一看,依然有很多东西思路不够清晰,很多时候是在生搬硬套,不求甚解,结果搞出来一些四不像的东西。

入行近十年,项目经验和开发经验应当是很丰富的,但是架构方面,确实是个新手,现在总算对相关技术有了一定的了解,因此打算从头再来一遍梳理,彻底的重构。
    之前参考别人的技术文章,加上自己的摸索,大致采用的模式是这样的,使用了MVC和Entityframework,Unity作为IOC容器,Model层和View层不必多说, Controller->Service ->Repository,Repository层通过Entityframework来实现数据的增删改查,业务逻辑放在Service层,通过UnitOfWork模式来实现多实体的事务控制,Controller层的职责就是调度,处理从UI层传过来的参数转换。

首先来说Repository层,首先定义了一个泛型接口,IRepository<Entity>,在里面定义了增删改查,然后定义了一个类
Repository<Entity>,实现IRepository<Entity>接口,同时为了考虑各实体特有的实现,为每个实体定义一个特有接口,以人员为例,定义IUserRepository接口,继承IRepository<User>,最终定义类UserRepository,继承Repository<User>,并实现IUserRepository接口。

所有的实体都是按照上述模式实现的,使用泛型,主要是实现了代码复用,这种模式在园子里也有不少人是这样用的。

关于Repository的定义和作用,园子里有很多文章提过多次了,在此我引用下(来源):

Repository是一个独立的层,介于领域层与数据映射层(数据访问层)之间。它的存在让领域层感觉不到数据访问层的存在,它提供一个类似集合的接口提供给领域层进行领域对象的访问。Repository是仓库管理员,领域层需要什么东西只需告诉仓库管理员,由仓库管理员把东西拿给它,并不需要知道东西实际放在哪。

由此可见,Repository是从领域驱动设计中的概念,从我的架构设计来说,并不是领域驱动的,没有聚合根的概念,对于Service层来说,需要一个DAL层来处理数据的存储和查询,因此,我这里使用Repository明显是一个误用。

关于Repository与DAL 区别如下:

Repository是DDD中的概念,强调Repository是受Domain驱动的,Repository中定义的功能要体现Domain的意图和约束,而Dal更纯粹的就是提供数据访问的功能,并不严格受限于Business层。

使用Repository,隐含着一种意图倾向,就是 Domain需要什么我才提供什么,不该提供的功能就不要提供,一切都是以Domain的需求为核心;而使用Dal,其意图倾向在于我Dal层能使用的数据库访问操作提供给Business层,你Business要用哪个自己选。换一个Business也可以用我这个Dal,一切是以我Dal能提供什么操作为核心。

这也就意味着,不应当在DAL层单独定义一个IUserRepository类来处理特有的接口方法,如用户不能被删除,而是应当在Service层里做控制,DAL单纯地提供对数据的查询和存储,不关心业务逻辑。

明确了上面的概念,下面就动手进行简化,有两种实现方式,一是使用泛型,二是使用T4模板或者代码生成器,这两种方式都能达到代码复用的目的。我这里采用的泛型,首先定义一个泛型接口IDAO<Entity>,泛型接口中定义方法也很明确:增、删、改、查,此前在IRepository定义了过多的重载方法,例如对于删除,定义了指定主键删除、指定实体删除和指定Lambda表达式删除,对于查询,定义了返回所有实体集合和返回单页数据集合。上述概念明确后,DAL层仅需要提供必要的几个方法即可,而对于同样功能的方法重载,放到Service层更合适。然后定义EFDAO<Entity>类实现该接口。这样做的好处不仅代码实现了复用,而且做到了面向接口编程,对于Service层来说,看到的只是IDAO接口,而不是具体的实现类。而IDAO是怎么实现的,是EntityFramework、NHibernate还是原生的sql,则可以灵活替代,变更数据访问层对整个系统无影响。

简而言之,我的框架实质是MVC模式加三层架构的结合体,View和Controller层基本不动,Model层细分为Model、Service/BLL、DAL三层。

以上是个人的反思和总结,把个人的误用经历、重构原因和最终实现方式发出来,供同道中人参考,欢迎批评指正,期待交流。

对Repository模式误用的反思和纠正的更多相关文章

  1. Asp.Net Core + Dapper + Repository 模式 + TDD 学习笔记

    0x00 前言 之前一直使用的是 EF ,做了一个简单的小项目后发现 EF 的表现并不是很好,就比如联表查询,因为现在的 EF Core 也没有啥好用的分析工具,所以也不知道该怎么写 Linq 生成出 ...

  2. 分享基于Entity Framework的Repository模式设计(附源码)

    关于Repository模式,在这篇文章中有介绍,Entity Framework返回IEnumerable还是IQueryable? 这篇文章介绍的是使用Entity Framework实现的Rep ...

  3. 关于MVC EF架构及Repository模式的一点心得

    一直都想写博客,可惜真的太懒了或者对自己的描述水平不太自信,所以...一直都是不想写的状态,关于领域驱动的东西看了不少,但是由于自己水平太差加上工作中实在用不到,所以一直处于搁置状态,最近心血来潮突然 ...

  4. 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【二】——使用Repository模式构建数据库访问层

    系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 前言 在数据访问层应用Repository模式来隔离对领域对象的细节操作是很有意义的.它位于映射层 ...

  5. (转)MVC中的Repository模式

    1.首先创建一个空的MVC3应用程序,命名为MyRepository.Web,解决方案命名为MyRepository. 2.添加一个类库项目,命名为MyRepository.DAL,添加一个文件夹命名 ...

  6. 关于Repository模式

    定义(来自Martin Fowler的<企业应用架构模式>): Mediates between the domain and data mapping layers using a co ...

  7. 探究Repository模式的两种写法与疑惑

    现如今DDD越来越流行,园子里漫天都是介绍关于它的文章.说到DDD就不能不提Repository模式了,有的地方也叫它仓储模式. 很多时候我们对Repository都还停留在Copy然后使用的阶段, ...

  8. LCLFramework框架之Repository模式

    Respository模式在示例中的实际目的小结一下 Repository模式是架构模式,在设计架构时,才有参考价值: Repository模式主要是封装数据查询和存储逻辑: Repository模式 ...

  9. Repository模式中,Update总是失败及其解析

    在Repository模式中,我的Update方法总是无法更新实体,这个非常郁闷,Update方法如下: 1: public virtual void Update(T entity) 2: { 3: ...

随机推荐

  1. KMP 初级板子 待更新

    复杂度 O(n+m) 这个博主写的蛮不错的 http://www.cnblogs.com/SYCstudio/p/7194315.html 1.本文中,所有的字符串从0开始编号2.为了在程序中表示方便 ...

  2. cent os下搭建简单的服务器

    作为常和网络打交道的程序员,经常会遇到需要服务器的场合,比如搭建一个web服务器,一个代理服务器,又或者一个小型的游戏服务器. 我时常和朋友一起玩一款叫我的世界的游戏,为了能够长期稳定地联机玩,所以特 ...

  3. The way to Go(1): Introduction

    Reference: Github: Go Github: The way to Go Introduction to Go 设计要求: 能够以更快的速度开发软件 开发出的软件能够很好地在现代的多核计 ...

  4. 【Coursera】Security Introduction -Eighth Week(2)

    Review -Terminology(术语): Confidentiallity & Integrity 泄密 & 欺骗 Confidentiallity: Prevent unau ...

  5. 【NOI2014】动物园

    题目链接:http://uoj.ac/problem/5 求:$${\prod _{i=1}^{L}num[i]\%(1e9+7)}$$,${num\left [ i \right ]}$表示:由字符 ...

  6. Ubuntu下配置JDK

    1. 首先你需要到oracle官网下载最新版本的JDK.跑到oracle官网,自己到Download下面找找吧 2.转到下载路径,对下载后的文件解压缩,比如我下载的文件名为jdk-7u7-linux- ...

  7. 更换主机后SSH无法登录的问题

    之前通过SSH远程一台机器(起个名字:cc),某一天把cc重装了一下系统,再SSH时显示密钥验证失败: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ...

  8. c++ 容器填充指定长度(fill_n)

    #include <iostream> // cout #include <algorithm> // fill_n #include <vector> // ve ...

  9. LIBS+=

    ZC: “LIBS+=”是要结合“LIBPATH += ”一起使用的?类似下面的用法: ZC: “LIBS+=”指明lib文件的名称,“LIBPATH += ”指明lib文件的路径.最后还要把DLL文 ...

  10. 《剑指offer》第二十一题(调整数组顺序使奇数位于偶数前面)

    // 面试题21:调整数组顺序使奇数位于偶数前面 // 题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有 // 奇数位于数组的前半部分,所有偶数位于数组的后半部分. #inclu ...