最近趁着不忙,在构思一个搭建一个开源的完整项目,至于原因以及整个项目框架后边文章我再说明。既然要起一个完整的项目,那么数据仓储访问就必不可少,这篇文章我主要介绍这个新项目(OSS.Core)中我对仓储层的简单思考和实现过程(当前项目还处在搭建阶段),主要集中在以下几个方面:

1. 数据仓储层的需求

2. ORM框架选择

3. OSS.Core仓储层设计实现

4. 调用示例

下边的实现部分中可能需要你对.NET的 泛型,委托,扩展,表达式等有一个基础了解。正是因为这些语言特性,方便我们对操作共性的抽取统一。

一. 数据仓储层需求

  既然是一个完整的项目,数据访问是其最基本的部分,同时,数据访问也是整个项目最容易出现瓶颈的地方。在我的划分中,其承担的角色是负责整个数据的输入输出,不仅仅是针对单数据库(有时甚至多库),有时还需要完成一级缓存的实现,给逻辑层提供最基础的数据支撑。

   业务永远是在变化的,那么项目也要具备快速演进的能力,所以我希望数据层能够保持相对的简单,在结构上尽量减少复杂的耦合查询,在性能上尽量减少不必要的消耗,例如反射的大量使用。同时针对每个业务对象完成数据库层面基本的CRUD统一封装实现。如果有需要的时候还能在最少的改动下加入缓存的更新。(对于如何实现不同模块不同缓存存储策略,像Redis,Memcached会在后边文章介绍)

  同时,对于一个稍微有点规模的项目来说,解决数据库访问的最快速做法就是实现读写分离,所以,我希望这个框架能够在一开始在底层就实现了读写分离的支持,以避免后期再重头对业务代码的大量修改。  

二. ORM 框架选择

  当然,如果为了简单和性能,直接ADO.NET连接理论上来说是比较高效的做法,不过这样会造成大量的重复操作逻辑代码,同时也会造成代码的散乱,增加维护复杂度。作为技术人员,不仅需要解决业务问题提高效率,同时也要提高自己的效率,所以我会选择一个ORM框架来完成部分基础工作。

  当前在.NET体系下,开源的ORM框架很多,如:Entityframework,NHibernate,iBATIS.NET,Dapper等等,各有特色,基于前面我说的,保证效率的同时,兼顾简单还能最大程度减少性能的损耗,并且提供.net standard标准库下的支持。这里对比之后我选择Dapper这个半自动化的ORM作为仓储层的基础框架,选择原因如下:

  1. 其结构简单,整个封装主要集中Dapper.cs文件中,体积很小

2. 封装功能简单强大,对原生SQL的支持上很灵活

    这点几乎完胜其他框架,无需任何多余的设置,同时基本上你可调用所有原生ADO.NET的功能,sql语句完全自己掌控,却又无需关心command的参数赋值,以及结果实体转换等。

  3. 性能上的高效

    很多ORM的实体映射通过反射来完成,这点上Dapper再次展现其魅力,在Commond参数赋值,以及实体转换等关键模块,使用了Reflection.Emit功能,间接实现了MSIL编译层面的赋值实现,之所以说间接,是因为其本身代码还需要编译器生成IL代码。在运行时根据类型属性动态创建赋值委托方法。

三. OSS.Core仓储层设计实现

   通过Dapper可以实现在数据库访问部分一层简单的封装,不过我依然需要手动编写不少的sql语句,同时还要进行参数化的处理,包括数据的读写分离等。那么这些功能的实现我将在OSS.Core.RepDapper中完成,为了方便理解,先贴出一个简单的封装后的方法调用传输流程:

  在这个图里展示一个简单的方法调用流程,围绕这张图的几个核心部分,我分别介绍下:

  1. 接口设计

  因为我希望这个是完整的示例项目,所以后边希望能够兼容不同数据库,因此对外的仓储访问都基于接口调用。当然如果你的项目根本没有切换数据库的需求,我更建议去掉这一环节,直接在基类中实现单例模式,业务逻辑层直接调用。

  图中可以看到接口层独立于实现部分,我将具体业务实体模型和接口 单独放在了OSS.Core.DomainMos 类库中,一方面是为了实体模型在各模块中的共用,另一方面解耦业务逻辑层(Services)和仓储层(Reps)之间的依赖关系。

  同时一个项目中数据库访问代码多数都会以CRUD为主,所以这里我定义了一个基础接口(IBaseRep),其包含的方法主要有(表达式部分在后边介绍):

  具体的业务数据接口继承至基础接口就好,其中表达式部分是我自己做了一个封装,后边会简单介绍。

  2. 仓储基类实现(BaseRep)

  首先,如图所示,我们实现了读写分离的两个扩展,其实最终都会经过Excute方法,那么这里展示下方法的具体实现:

  可以看到在这个方法提供了一个针对IDbConnection的委托,提供调用层自由使用Dapper方法的同时,统一了数据访问方法入口,便于日志记录,和排查。

  其次,在很多项目中会出现用户和订单在不同库中的这类情况,因为涉及到分库的情况,所以需要子类中能有修改连接串能力,那么这里我通过构造函数的形式,提供了两个可空参数:

  可以看到,如果子类中定义了自己的连接串,则以子类自定义为主,否则走默认的连接信息。

  

  最后,我们也实现了针对基础接口方法的具体实现,举一示例:

  同时,为了保证子类中能够加入缓存处理,所以采用了虚方法(virtual)的形式,保证子类能够重写。

  3. 基于Connection的扩展

  这个地方主要分为两个部分,a. 表达式的解析,以及参数化的处理   b. 扩展Connection的Insert,Update...等Dapper没有扩展的方法:

  a. 熟悉Expression表达式的朋友应该比较了解,表达式本身是一个树形接口,根据不同的类型,可以不断的解析其子表达式,直到不具备继续解析的可能。所以这个就很简单就是递归的不断迭代,根据其不同的NodeType可以组装不同的sql元素,因为代码较长,可以参见github下的SqlExpressionVisitor.cs类,其中参数的赋值部分,没有采用反射,而是使用的反射发射,代码详见SqlParameterEmit.cs

  b. 有了表达式的扩展之后,就可以获取对应的sql和参数,通过this扩展Connection方法即可,代码见ConnoctionExtention.cs

  

四. 调用示例

  1. 我们定义一个简单UserInfoMo实体(包含mobile等属性)

  2. 定义接口  IUserInfoRep: IBaseRep

  3. 定义实现类  UserInfoRep : BaseRep, IUserInfoRep

  在不添加其他代码的基础上,我们就可以完成下面的调用:

本文转自xmgdc51CTO博客,原文链接: http://blog.51cto.com/12953214/1942916,如需转载请自行联系原作者

OSS.Core基于Dapper封装(表达式解析+Emit)仓储层的构思及实现相关推荐

  1. .net core 基于Dapper 的分库分表开源框架(core-data)

    一.前言 感觉很久没写文章了,最近也比较忙,写的相对比较少,抽空分享基于Dapper 的分库分表开源框架core-data的强大功能,更好的提高开发过程中的效率:在数据库的数据日积月累的积累下,业务数 ...

  2. dapper框架_.net core 基于Dapper 的分库分表开源框架(core-data)

    一.前言 感觉很久没写文章了,最近也比较忙,写的相对比较少,抽空分享基于Dapper 的分库分表开源框架core-data的强大功能,更好的提高开发过程中的效率: 在数据库的数据日积月累的积累下,业务 ...

  3. .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现...

    本篇我将带着大家一起来对Dapper进行下封装并实现基本的增删改查.分页操作的同步异步方法的实现(已实现MSSQL,MySql,PgSQL).同时我们再实现一下仓储层的代码生成器,这样的话,我们只需要 ...

  4. ASP.NET Core 实战:基于 Dapper 扩展你的数据访问方法

    ASP.NET Core 实战:基于 Dapper 扩展你的数据访问方法 一.前言 在非静态页面的项目开发中,必定会涉及到对于数据库的访问,最开始呢,我们使用 Ado.Net,通过编写 SQL 帮助类 ...

  5. 基于Dapper二次封装了一个易用的ORM工具类:SqlDapperUtil

    基于Dapper二次封装了一个易用的ORM工具类:SqlDapperUtil,把日常能用到的各种CRUD都进行了简化封装,让普通程序员只需关注业务即可,因为非常简单,故直接贴源代码,大家若需使用可以直 ...

  6. Dapper.Common基于Dapper的开源LINQ超轻量扩展

    Dapper.Common Dapper.Common是基于Dapper的LINQ实现,支持.net core,遵循Linq语法规则.链式调用.配置简单.上手快,支持Mysql,Sqlserver(目 ...

  7. dapper mysql 拓展_Dapper.Common基于Dapper的开源LINQ超轻量扩展

    Dapper.Common Dapper.Common是基于Dapper的LINQ实现,支持.net core,遵循Linq语法规则.链式调用.配置简单.上手快,支持Mysql,Sqlserver(目 ...

  8. 基于Dapper的开源Lambda扩展,且支持分库分表自动生成实体

    LnskyDB是基于Dapper的Lambda扩展,支持按时间分库分表,也可以自定义分库分表方法 开源地址 https://github.com/liningit/LnskyDB 在此非常感谢SkyC ...

  9. dapperpoco mysql_DapperPoco -- 基于Dapper的、轻量级的、高性能的、简单的、灵活的ORM框架...

    为什么要重复造轮子 因为现有的轮子都在某些方面不太令我满意,下面我来一一点评一下,欢迎拍砖. Entity Framework 我喜欢傻瓜化使用方式的框架,同时又不失灵活性. EF虽然使用起来足够简单 ...

最新文章

  1. 算法基础知识科普:8大搜索算法之红黑树(中)
  2. Flex3.0 图片浏览器(平移、光标中心点放缩、任意角度旋转)
  3. 深入剖析ASP.NET的编译原理之一:动态编译(Dynamical Compilation)
  4. VisualVM——JDK自带的性能分析工具
  5. Net 分页功能的实现
  6. php增加mysql索引_mysql怎么添加索引
  7. 【MySQL】MySQL常见的读写分离方法
  8. 第二阶段团队冲刺第三天
  9. mongo 修改器 $inc/$set/$unset/$pop/$push/$pull/$addToSet
  10. lynis check log
  11. meshlab点云颜色偏暗
  12. 详解验证码与打码平台的攻防对抗
  13. THREE.js开荒小记(二):无效宽度linewidth的Line 和 无效阔threshold的Line2
  14. 《陶哲轩实分析》阅读
  15. u盘复制一直正在计算机,解决U盘复制文件时电脑总是重启的方法
  16. web编程技术基础---CSS
  17. 【正点原子STM32连载】第四十六章 FATFS实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1
  18. linux screen窗口 jupyter notebook 激活环境后无法切换到指定虚拟环境
  19. 大学小说男主计算机,一部小说,男女主是大学校友,男主比较高冷,一次聚会上认识,男主对女主一见钟情,然后带去出租屋里睡了...
  20. Games104现代游戏引擎入门-lecture12游戏引擎的粒子和声效系统

热门文章

  1. jenkins添加git源码目录时报Error performing command错误
  2. ECHO.js 纯javascript轻量级延迟加载
  3. 经典算法题每日演练——第六题 协同推荐SlopeOne 算法
  4. Win7封装无损廋身清单
  5. 现代软件工程 第十章 【典型用户和场景】 练习与讨论
  6. 函数图像轻松画:教你用永中图象
  7. 《CLR via C#》笔记——CLR的执行模型
  8. SSIS中的记录集目标
  9. ASP中的常用服务器检测源码
  10. 大三下学期第一周总结