dapper框架_.net core 基于Dapper 的分库分表开源框架(core-data)
![](/assets/blank.gif)
一、前言
感觉很久没写文章了,最近也比较忙,写的相对比较少,抽空分享基于Dapper
的分库分表开源框架core-data
的强大功能,更好的提高开发过程中的效率; 在数据库的数据日积月累的积累下,业务数据库中的单表数据想必也越来越大,大到百万、千万、甚至上亿级别的数据,这个时候就很有必要进行数据库读写分离、以及单表分多表进行存储,提高性能,但是呢很多人不知道怎么去分库分表,也没有现成的分库分表的成熟框架,故不知道怎么下手,又怕影响到业务;现在我给大家推荐core-data
的分库分表开源框架。框架开源地址:https://github.com/overtly/core-data
二、基础
2.1 回顾
这里先来回顾下我上一篇文章中的技术栈路线图,如下:
![](/assets/blank.gif)
今天从这张技术栈图中来详细分享一切的基础数据库底层操作ORM。
2.2 core-data主要优势:
上一篇文章.Net 微服务架构技术栈的那些事 中简单的介绍了core-data
主要优势,如下:
- 官方建议使用DDD 领域驱动设计思想开发
- 支持多种数据库(MySql / SqlServer / SQLite ),简单配置添加链接的配置即可
- 支持分表操作,自定义分表策略的支持
- 支持表达式方式编写,减少写Sql语句机械性工作
- 可对Dapper 进行扩展
- 性能依赖于Dapper 本身的性能,Dapper 本身是轻量级ORM ,官方测试性能都强于其他的ORM
- 框架支持Framework4.6 - NetStandard 2.0
三、实战详解
这里都仅仅分享核心的内容代码,不把整个代码贴出来,有需要完整Demo源代码请访问 https://github.com/a312586670/NetCoreDemo 在我的解决方案的项目中 引用overt.core.data
nuget包,如下图:
![](/assets/blank.gif)
3.1 单表模式
创建用户实体代码如下:
/// <summary>/// 标注数据库对应的表名/// </summary>[Table("User")]public class UserEntity{/// <summary>/// 主键ID,标注自增ID/// </summary>[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]public int UserId { get; set; }/// <summary>/// 商户ID/// </summary>public int MerchantId { set; get; }/// <summary>/// 用户名/// </summary>public string UserName { get; set; }/// <summary>/// 真实姓名/// </summary>public string RealName { get; set; }/// <summary>/// 密码/// </summary>public string Password { get; set; }/// <summary>/// 添加时间/// </summary>public DateTime AddTime { get; set; }}
代码中通过[Table("User")]
来和数据库表进行映射关联; 通过[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 标注自增主键.
3.2 默认分表策略
从单表模式改成分表模式,并且按照商户的模式进行分表,代码实体代码改造如下:
/// <summary>/// 标注数据库对于的表名/// </summary>[Table("User")]public class UserEntity{/// <summary>/// 主键ID,标注自增ID/// </summary>[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]public int UserId { get; set; }/// <summary>/// 商户ID/// </summary>[Submeter(Bit =2)]public int MerchantId { set; get; }/// <summary>/// 用户名/// </summary>public string UserName { get; set; }/// <summary>/// 真实姓名/// </summary>public string RealName { get; set; }/// <summary>/// 密码/// </summary>public string Password { get; set; }/// <summary>/// 添加时间/// </summary>public DateTime AddTime { get; set; }}
代码中 MerchantId 字段上添加了[Submeter(Bit =2)]
标注,并且指定了Bit=2,将会分成根据MerchantId字段取二进制进行md5 hash 取前两位分成256张表
分表模式源码分析
分表模式可以通过在字段上标注Submeter
属性,我们先来看看框架对于这个标注的源代码,源代码如下:
/// <summary>/// 分表标识/// </summary>public class SubmeterAttribute : Attribute{/// <summary>/// 16进制位数/// 1 16/// 2 256/// 3 4096 /// .../// </summary>public int Bit { get; set; }}
开源框架中其中一个获得分表的表名称的扩展方法,仅仅只贴了一个扩展方法,有兴趣的可以下载开源框架进行源码阅读。
/// <summary>/// 获取表名/// </summary>/// <param name="entity">实体实例</param>/// <param name="tableNameFunc"></param>/// <returns></returns>public static string GetTableName<TEntity>(this TEntity entity, Func<string> tableNameFunc = null) where TEntity : class, new(){if (tableNameFunc != null)return tableNameFunc.Invoke();var t = typeof(TEntity);var mTableName = t.GetMainTableName();var propertyInfo = t.GetProperty<SubmeterAttribute>();if (propertyInfo == null) // 代表没有分表特性return mTableName;// 获取分表var suffix = propertyInfo.GetSuffix(entity);return $"{mTableName}_{suffix}";}/// <summary>/// 获取后缀(默认根据SubmeterAttribute 标注的位数进行Md5 hash 进行分表)/// </summary>/// <param name="val"></param>/// <param name="bit"></param>/// <returns></returns>internal static string GetSuffix(string val, int bit = 2){if (string.IsNullOrEmpty(val))throw new ArgumentNullException($"分表数据为空");if (bit <= 0)throw new ArgumentOutOfRangeException("length", "length必须是大于零的值。");var result = Encoding.Default.GetBytes(val.ToString()); //tbPass为输入密码的文本框var md5Provider = new MD5CryptoServiceProvider();var output = md5Provider.ComputeHash(result);var hash = BitConverter.ToString(output).Replace("-", ""); //tbMd5pass为输出加密文本var suffix = hash.Substring(0, bit).ToUpper();return suffix;}
源代码中通过SubmeterAttribute
特性进行对字段进行标注分表,可以传对应的bit参数进行框架默认的分表策略进行分表,但是很多情况下我们需要自定义分表策略,那我们应该怎么去自定义分表策略呢?我们先等一下来实践自定义分表策略,先来创建用户的Repository
,代码如下 IUserRepository
:
public interface IUserRepository : IBaseRepository<UserEntity>
{
}
需要继承IBaseRepository<T>
的接口,该接口默认实现了基本的方法,开源框架中IBaseRepository<T>
代码方法如下图:
![](/assets/blank.gif)
创建完IUserRepository
接口后,我们来创建它的实现UserRepository
,代码如下:
public class UserRepository : BaseRepository<UserEntity>, IUserRepository
{public UserRepository(IConfiguration configuration): base(configuration, "user"){}}
从代码中UserRepository
类继承了BaseRepository<T>
类,我们来看看这个abstract类的基本结构,如下图:
![](/assets/blank.gif)
开源框架中BaseRepository<T>
抽象类继承了PropertyAssist
类,我们再来看看它的有哪些方法,如下图:
![](/assets/blank.gif)
从图中可以看到定义了一系列的virtual
方法,那既然是virtual
方法我们就可以进行重写
CreateScriptFunc
:自动创建脚本数据表方法TableNameFunc
:可以进行自定义分表策略
3.3 自定义分表策略
我们来实现上面提出的自定义分表策略问题(根据商户Id来进行分表,并且自动把不存在的表进行初始化创建),代码改造如下: IUserRepository
:
public interface IUserRepository : IBaseRepository<UserEntity>
{int MerchantId { set; get; }
}
UserRepository
代码改造如下:
public class UserRepository : BaseRepository<UserEntity>, IUserRepository
{public UserRepository(IConfiguration configuration): base(configuration, "user"){}/// <summary>/// 用于根据商户ID来进行分表/// </summary>public int MerchantId { set; get; }//自定义分表策略public override Func<string> TableNameFunc => () =>{var tableName = $"{GetMainTableName()}_{MerchantId}";return tableName;};//自动创建分表的脚本public override Func<string, string> CreateScriptFunc => (tableName) =>{//MySqlreturn "CREATE TABLE `" + tableName + "` (" +" `UserId` int(11) NOT NULL AUTO_INCREMENT," +" `UserName` varchar(200) DEFAULT NULL," +" `Password` varchar(200) DEFAULT NULL," +" `RealName` varchar(200) DEFAULT NULL," +" `AddTime` datetime DEFAULT NULL," +" `MerchantId` int(11) NOT NULL," +" PRIMARY KEY(`UserId`)" +") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8mb4; ";};}
3.4 数据库读写分离
我们再来看看开源框架的基类代码结构截图,如下:
![](/assets/blank.gif)
对于查询的基本常用的方法都有一个isMaster=false
的参数,该参数就是用于是否读取主库,用于基本的主从数据库的分离,也就是读写分离,那改怎么配置读写分离数据库呢 链接字符串如下图:
![](/assets/blank.gif)
分别指定了主从数据库的链接字符串. 我们来分析源代码,核心框架源代码如下:
/// <summary>
/// 连接配置信息获取
/// 1. master / secondary
/// 2. xx.master / xx.secondary
/// </summary>
public class DataSettings
{#region Static Private Membersstatic readonly string _connNmeOfMaster = "master";static readonly string _connNameOfSecondary = "secondary";static readonly string _connNameOfPoint = ".";static string _connNameOfPrefix = "";#endregion#region Private Member/// <summary>/// 主库/// </summary>private string Master{get { return $"{_connNameOfPrefix}{_connNmeOfMaster}"; }}/// <summary>/// 从库/// </summary>private string Secondary{get{return $"{_connNameOfPrefix}{_connNameOfSecondary}";}}#endregion/// <summary>/// 获取链接名称/// </summary>/// <param name="isMaster"></param>/// <param name="store">不能包含点</param>/// <returns></returns>private string Key(bool isMaster = false, string store = ""){_connNameOfPrefix = string.IsNullOrEmpty(store) ? "" : $"{store}{_connNameOfPoint}";var connName = string.Empty;if (isMaster)connName = Master;elseconnName = Secondary;return connName;}
}
代码中根据isMaster 参数来进行读写数据库链接参数的获取,以达到读写分离的功能,同时还支持前缀的配置支持,也开源自由配置多个数据库进行读取,只需要构造函数中获取配置即可。 上面的分表Demo 单元测试运行后的结果例子如下图:
![](/assets/blank.gif)
已经按照MerchantId 字段进行分表
三、总结
到这里用户表已经根据商户ID进行分表存储了,这样就做到了读写分离及自定义分表策略存储数据,core-data
开源框架还支持更多的强大功能,实现了一系列的基础CRUD的方法,不用写任何的sql语句,Where表达式的支持,同时可以自定义复杂的sql语句,更多请访问框架开源地址:https://github.com/overtly/core-data. 完整的Demo 代码 已经放在github上,Demo代码结构图如下:
![](/assets/blank.gif)
地址:https://github.com/a312586670/NetCoreDemo
原创不易,觉得对你有帮助请给一个赞
dapper框架_.net core 基于Dapper 的分库分表开源框架(core-data)相关推荐
- .net core 基于Dapper 的分库分表开源框架(core-data)
一.前言 感觉很久没写文章了,最近也比较忙,写的相对比较少,抽空分享基于Dapper 的分库分表开源框架core-data的强大功能,更好的提高开发过程中的效率:在数据库的数据日积月累的积累下,业务数 ...
- 开源分布式数据库中间件MyCat架构简介(二)——基于MyCat的分库分表,读写分离,水平切分和垂直切分实现原理
目录 前言 基于MyCat的分库分表,读写分离,水平切分和垂直切分实现原理 一.关于Mycat 二.Mycat 实现原理 三.MyCat 应用场景 四.MyCat 未来展望 五.Mycat 中相关概念 ...
- 开源分布式数据库中间件MyCat架构简介(一)——基于MyCat的分库分表,读写分离,水平切分和垂直切分实现原理
目录 前言 开源分布式数据库中间件MyCat架构简介--MyCat源起 一.数据库切分概述:OLTP和OLAP 二.关系型数据库和NoSQL数据库 三.关系型数据库和NoSQL数据库的特点及优缺点 1 ...
- mysql多字段分库分表基因码_一文学会常用 MySQL 分库分表方案
来源 | https://www.cnblogs.com/littlecharacter/p/9342129.html 一.数据库瓶颈 不管是IO瓶颈,还是CPU瓶颈,最终都会导致数据库的活跃连接数增 ...
- python数据库框架_目前最受欢迎的12个Python开源框架
1 Django Django是一款用Python语言写的免费开源的 Python Web应用开发框架,它遵循模型 -视图-控制器(MVC)的架构模式.它是由非营利Django维护软件基金会(DSF) ...
- 基于SpringCloud实现Shard-Jdbc的分库分表模式,数据库扩容方案
一.项目结构 1.工程结构 2.模块命名 shard-common-entity: 公共代码块 shard-open-inte: 开放接口管理 shard-eureka-7001: 注册中心 shar ...
- 架构组件:基于Shard-Jdbc分库分表,数据库扩容方案
架构组件:基于Shard-Jdbc分库分表,数据库扩容方案 一.数据库扩容 1.业务场景 互联网项目中有很多"数据量大,业务复杂度高,需要分库分表"的业务场景. 这样分层的架构 ( ...
- 数据库查询某一列大写转化小写字母表示_基于MySQL数据库下亿级数据的分库分表...
每天给你诚意满满的干货 本文来自程序之心知乎专栏收到的投稿 作者:恒生研究院 移动互联网时代,海量的用户数据每天都在产生,基于用户使用数据等这样的分析,都需要依靠数据统计和分析,当数据量小时,数据库方 ...
- 基于代理的数据库分库分表框架 Mycat实践
192.168.199.75 MySQL . MyCAT master 192.168.199.74 MySQL slave 192.168.199.76 MySQL standby master 如 ...
最新文章
- thinkphp5.1嵌套关联预载入的写法
- pytorch 保存网络的时候值得注意的事情
- RtlAdjustPrivilege() 提权函数
- mysql无法添加或更新子行_MySQL错误1452-无法添加或更新子行:外键约束失败?
- Redis学习总结(18)——Redis 常见面试题复习
- python读取超大文件-强悍的Python读取大文件的解决方案
- excel学习1:合并两个单元格,并把内容用符号隔开。
- C语言pow函数的调用
- SAP中由生产版本有误导致的生产报工时提示“错误确定成本核算”问题实例
- 第2期:大数据岗位有哪些
- pycharmSDK is not defined for Run Configuration 解决
- python3 selenium模块Chrome设置代理ip的实现
- BGP比较基础的实验
- 05-Spring反转控制IOC 与 依赖注入DI概念
- 使用HTML制作个人简历
- 基于jQuery仿QQ音乐播放器网页版代码
- 高仿精仿好123网站导航源码完整最新版
- python——class类和方法的用法详解
- 10个明亮的圣诞照片滤镜LR预设模板 10 Bright Christmas Desktop Mobile presets
- python如何限制数字范围_python – 如何找到数字范围
热门文章
- Speaker Recognition: Feature Extraction
- mysql 自定义函数教程_Mysql 自定义函数
- mysql如何进行数据透视,mysql-如何优化数据透视表的条件检查?
- 24.redis持久化之AOF
- Linux tmux 使用指南
- ubuntu16.04 安装python3.6
- HNCU1324:算法2-2:有序线性表的有序合并(线性表)
- I will have to learn more skills now , now
- Silverlight中动画的性能浅析
- 演练nerddinner 问题