上海交通大学文科建设处网站,网站模板 免费下载,wordpress 过多的重定向,网络营销方式和技巧一、前言感觉很久没写文章了#xff0c;最近也比较忙#xff0c;写的相对比较少#xff0c;抽空分享基于Dapper 的分库分表开源框架core-data的强大功能#xff0c;更好的提高开发过程中的效率#xff1b;在数据库的数据日积月累的积累下#xff0c;业务数据库中的单表数… 一、前言感觉很久没写文章了最近也比较忙写的相对比较少抽空分享基于Dapper 的分库分表开源框架core-data的强大功能更好的提高开发过程中的效率在数据库的数据日积月累的积累下业务数据库中的单表数据想必也越来越大大到百万、千万、甚至上亿级别的数据这个时候就很有必要进行数据库读写分离、以及单表分多表进行存储提高性能但是呢很多人不知道怎么去分库分表也没有现成的分库分表的成熟框架故不知道怎么下手又怕影响到业务现在我给大家推荐core-data的分库分表开源框架。框架开源地址:https://github.com/overtly/core-data二、基础2.1 回顾这里先来回顾下我上一篇文章中的技术栈路线图如下今天从这张技术栈图中来详细分享一切的基础数据库底层操作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包如下图3.1 单表模式创建用户实体代码如下 /// summary/// 标注数据库对应的表名/// /summary[Table(User)]public class UserEntity{/// summary/// 主键ID,标注自增ID/// /summary[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]public int UserId { get; set; }/// summary/// 商户ID/// /summarypublic int MerchantId { set; get; }/// summary/// 用户名/// /summarypublic string UserName { get; set; }/// summary/// 真实姓名/// /summarypublic string RealName { get; set; }/// summary/// 密码/// /summarypublic string Password { get; set; }/// summary/// 添加时间/// /summarypublic 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/// 用户名/// /summarypublic string UserName { get; set; }/// summary/// 真实姓名/// /summarypublic string RealName { get; set; }/// summary/// 密码/// /summarypublic string Password { get; set; }/// summary/// 添加时间/// /summarypublic DateTime AddTime { get; set; }}代码中 MerchantId 字段上添加了[Submeter(Bit 2)]标注并且指定了Bit2将会分成根据MerchantId字段取二进制进行md5 hash 取前两位分成256张表分表模式源码分析分表模式可以通过在字段上标注Submeter属性我们先来看看框架对于这个标注的源代码源代码如下 /// summary/// 分表标识/// /summarypublic class SubmeterAttribute : Attribute{/// summary/// 16进制位数/// 1 16/// 2 256/// 3 4096/// .../// /summarypublic int Bit { get; set; }}
开源框架中其中一个获得分表的表名称的扩展方法仅仅只贴了一个扩展方法有兴趣的可以下载开源框架进行源码阅读。 /// summary/// 获取表名/// /summary/// param nameentity实体实例/param/// param nametableNameFunc/param/// returns/returnspublic static string GetTableNameTEntity(this TEntity entity, Funcstring tableNameFunc null) where TEntity : class, new(){if (tableNameFunc ! null)return tableNameFunc.Invoke();var t typeof(TEntity);var mTableName t.GetMainTableName();var propertyInfo t.GetPropertySubmeterAttribute();if (propertyInfo null) // 代表没有分表特性return mTableName;// 获取分表var suffix propertyInfo.GetSuffix(entity);return ${mTableName}_{suffix};}/// summary/// 获取后缀(默认根据SubmeterAttribute 标注的位数进行Md5 hash 进行分表)/// /summary/// param nameval/param/// param namebit/param/// returns/returnsinternal 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 : IBaseRepositoryUserEntity
{
}
需要继承IBaseRepositoryT的接口该接口默认实现了基本的方法开源框架中IBaseRepositoryT代码方法如下图创建完IUserRepository接口后我们来创建它的实现UserRepository,代码如下public class UserRepository : BaseRepositoryUserEntity, IUserRepository
{public UserRepository(IConfiguration configuration): base(configuration, user){}}
从代码中UserRepository类继承了BaseRepositoryT类我们来看看这个abstract类的基本结构如下图:开源框架中BaseRepositoryT抽象类继承了PropertyAssist类我们再来看看它的有哪些方法如下图从图中可以看到定义了一系列的virtual方法那既然是virtual方法我们就可以进行重写CreateScriptFunc:自动创建脚本数据表方法TableNameFunc可以进行自定义分表策略3.3 自定义分表策略我们来实现上面提出的自定义分表策略问题根据商户Id来进行分表,并且自动把不存在的表进行初始化创建代码改造如下IUserRepository:public interface IUserRepository : IBaseRepositoryUserEntity
{int MerchantId { set; get; }
}
UserRepository 代码改造如下public class UserRepository : BaseRepositoryUserEntity, IUserRepository
{public UserRepository(IConfiguration configuration): base(configuration, user){}/// summary/// 用于根据商户ID来进行分表/// /summarypublic int MerchantId { set; get; }//自定义分表策略public override Funcstring TableNameFunc () {var tableName ${GetMainTableName()}_{MerchantId};return tableName;};//自动创建分表的脚本public override Funcstring, 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 数据库读写分离我们再来看看开源框架的基类代码结构截图如下对于查询的基本常用的方法都有一个isMasterfalse的参数该参数就是用于是否读取主库用于基本的主从数据库的分离也就是读写分离那改怎么配置读写分离数据库呢 链接字符串如下图分别指定了主从数据库的链接字符串. 我们来分析源代码核心框架源代码如下/// 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/// 主库/// /summaryprivate string Master{get { return ${_connNameOfPrefix}{_connNmeOfMaster}; }}/// summary/// 从库/// /summaryprivate string Secondary{get{return ${_connNameOfPrefix}{_connNameOfSecondary};}}#endregion/// summary/// 获取链接名称/// /summary/// param nameisMaster/param/// param namestore不能包含点/param/// returns/returnsprivate 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 单元测试运行后的结果例子如下图已经按照MerchantId 字段进行分表三、总结到这里用户表已经根据商户ID进行分表存储了这样就做到了读写分离及自定义分表策略存储数据core-data 开源框架还支持更多的强大功能实现了一系列的基础CRUD的方法不用写任何的sql语句Where表达式的支持同时可以自定义复杂的sql语句更多请访问框架开源地址:https://github.com/overtly/core-data. 完整的Demo 代码 已经放在github上Demo代码结构图如下:地址https://github.com/a312586670/NetCoreDemo原创不易觉得对你有帮助请给一个赞往期精彩回顾【.net core】电商平台升级之微服务架构应用实战.Net Core微服务架构技术栈的那些事Asp.Net Core 中IdentityServer4 授权中心之应用实战Asp.Net Core 中IdentityServer4 授权中心之自定义授权模式Asp.Net Core 中IdentityServer4 授权流程及刷新TokenAsp.Net Core 中IdentityServer4 实战之 Claim详解Asp.Net Core 中IdentityServer4 实战之角色授权详解Asp.Net Core 中间件应用实战中你不知道的那些事Asp.Net Core Filter 深入浅出的那些事-AOPAsp.Net Core EndPoint 终结点路由工作原理解读ASP.NET CORE 内置的IOC解读及使用♥ 给个[在看]是对我最大的支持 ♥