日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

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

發(fā)布時(shí)間:2023/12/4 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 .net core 基于Dapper 的分库分表开源框架(core-data) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、前言

感覺很久沒寫文章了,最近也比較忙,寫的相對(duì)比較少,抽空分享基于Dapper 的分庫(kù)分表開源框架core-data的強(qiáng)大功能,更好的提高開發(fā)過(guò)程中的效率;在數(shù)據(jù)庫(kù)的數(shù)據(jù)日積月累的積累下,業(yè)務(wù)數(shù)據(jù)庫(kù)中的單表數(shù)據(jù)想必也越來(lái)越大,大到百萬(wàn)、千萬(wàn)、甚至上億級(jí)別的數(shù)據(jù),這個(gè)時(shí)候就很有必要進(jìn)行數(shù)據(jù)庫(kù)讀寫分離、以及單表分多表進(jìn)行存儲(chǔ),提高性能,但是呢很多人不知道怎么去分庫(kù)分表,也沒有現(xiàn)成的分庫(kù)分表的成熟框架,故不知道怎么下手,又怕影響到業(yè)務(wù);現(xiàn)在我給大家推薦core-data的分庫(kù)分表開源框架。框架開源地址:https://github.com/overtly/core-data

二、基礎(chǔ)

2.1 回顧

這里先來(lái)回顧下我上一篇文章中的技術(shù)棧路線圖,如下:今天從這張技術(shù)棧圖中來(lái)詳細(xì)分享一切的基礎(chǔ)數(shù)據(jù)庫(kù)底層操作ORM。

2.2 core-data主要優(yōu)勢(shì):

上一篇文章.Net 微服務(wù)架構(gòu)技術(shù)棧的那些事 中簡(jiǎn)單的介紹了core-data主要優(yōu)勢(shì),如下:

  • 官方建議使用DDD 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)思想開發(fā)

  • 支持多種數(shù)據(jù)庫(kù)(MySql / SqlServer / SQLite ),簡(jiǎn)單配置添加鏈接的配置即可

  • 支持分表操作,自定義分表策略的支持

  • 支持表達(dá)式方式編寫,減少寫Sql語(yǔ)句機(jī)械性工作

  • 可對(duì)Dapper 進(jìn)行擴(kuò)展

  • 性能依賴于Dapper 本身的性能,Dapper 本身是輕量級(jí)ORM ,官方測(cè)試性能都強(qiáng)于其他的ORM

  • 框架支持Framework4.6 - NetStandard 2.0

三、實(shí)戰(zhàn)詳解

這里都僅僅分享核心的內(nèi)容代碼,不把整個(gè)代碼貼出來(lái),有需要完整Demo源代碼請(qǐng)?jiān)L問 https://github.com/a312586670/NetCoreDemo 在我的解決方案的項(xiàng)目中 引用overt.core.data nuget包,如下圖:

3.1 單表模式

創(chuàng)建用戶實(shí)體代碼如下:

/// <summary>/// 標(biāo)注數(shù)據(jù)庫(kù)對(duì)應(yīng)的表名/// </summary>[Table("User")]public class UserEntity{/// <summary>/// 主鍵ID,標(biāo)注自增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>/// 真實(shí)姓名/// </summary>public string RealName { get; set; }/// <summary>/// 密碼/// </summary>public string Password { get; set; }/// <summary>/// 添加時(shí)間/// </summary>public DateTime AddTime { get; set; }}

代碼中通過(guò)[Table("User")] 來(lái)和數(shù)據(jù)庫(kù)表進(jìn)行映射關(guān)聯(lián);通過(guò)[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 標(biāo)注自增主鍵.

3.2 默認(rèn)分表策略

從單表模式改成分表模式,并且按照商戶的模式進(jìn)行分表,代碼實(shí)體代碼改造如下:

/// <summary>/// 標(biāo)注數(shù)據(jù)庫(kù)對(duì)于的表名/// </summary>[Table("User")]public class UserEntity{/// <summary>/// 主鍵ID,標(biāo)注自增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>/// 真實(shí)姓名/// </summary>public string RealName { get; set; }/// <summary>/// 密碼/// </summary>public string Password { get; set; }/// <summary>/// 添加時(shí)間/// </summary>public DateTime AddTime { get; set; }}

代碼中 MerchantId 字段上添加了[Submeter(Bit =2)]標(biāo)注,并且指定了Bit=2,將會(huì)分成根據(jù)MerchantId字段取二進(jìn)制進(jìn)行md5 hash 取前兩位分成256張表

分表模式源碼分析

分表模式可以通過(guò)在字段上標(biāo)注Submeter屬性,我們先來(lái)看看框架對(duì)于這個(gè)標(biāo)注的源代碼,源代碼如下:

/// <summary>/// 分表標(biāo)識(shí)/// </summary>public class SubmeterAttribute : Attribute{/// <summary>/// 16進(jìn)制位數(shù)/// 1 16/// 2 256/// 3 4096/// .../// </summary>public int Bit { get; set; }}

開源框架中其中一個(gè)獲得分表的表名稱的擴(kuò)展方法,僅僅只貼了一個(gè)擴(kuò)展方法,有興趣的可以下載開源框架進(jìn)行源碼閱讀。

/// <summary>/// 獲取表名/// </summary>/// <param name="entity">實(shí)體實(shí)例</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>/// 獲取后綴(默認(rèn)根據(jù)SubmeterAttribute 標(biāo)注的位數(shù)進(jìn)行Md5 hash 進(jìn)行分表)/// </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($"分表數(shù)據(jù)為空");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;}

源代碼中通過(guò)SubmeterAttribute 特性進(jìn)行對(duì)字段進(jìn)行標(biāo)注分表,可以傳對(duì)應(yīng)的bit參數(shù)進(jìn)行框架默認(rèn)的分表策略進(jìn)行分表,但是很多情況下我們需要自定義分表策略,那我們應(yīng)該怎么去自定義分表策略呢?我們先等一下來(lái)實(shí)踐自定義分表策略,先來(lái)創(chuàng)建用戶的Repository,代碼如下IUserRepository:

public interface IUserRepository : IBaseRepository<UserEntity> { }

需要繼承IBaseRepository<T>的接口,該接口默認(rèn)實(shí)現(xiàn)了基本的方法,開源框架中IBaseRepository<T>代碼方法如下圖:創(chuàng)建完IUserRepository接口后,我們來(lái)創(chuàng)建它的實(shí)現(xiàn)UserRepository,代碼如下:

public class UserRepository : BaseRepository<UserEntity>, IUserRepository {public UserRepository(IConfiguration configuration): base(configuration, "user"){}}

從代碼中UserRepository類繼承了BaseRepository<T>類,我們來(lái)看看這個(gè)abstract類的基本結(jié)構(gòu),如下圖:開源框架中BaseRepository<T>抽象類繼承了PropertyAssist類,我們?cè)賮?lái)看看它的有哪些方法,如下圖:從圖中可以看到定義了一系列的virtual方法,那既然是virtual方法我們就可以進(jìn)行重寫

  • CreateScriptFunc:自動(dòng)創(chuàng)建腳本數(shù)據(jù)表方法

  • TableNameFunc:可以進(jìn)行自定義分表策略

3.3 自定義分表策略

我們來(lái)實(shí)現(xiàn)上面提出的自定義分表策略問題(根據(jù)商戶Id來(lái)進(jìn)行分表,并且自動(dòng)把不存在的表進(jìn)行初始化創(chuàng)建),代碼改造如下: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>/// 用于根據(jù)商戶ID來(lái)進(jìn)行分表/// </summary>public int MerchantId { set; get; }//自定義分表策略public override Func<string> TableNameFunc => () =>{var tableName = $"{GetMainTableName()}_{MerchantId}";return tableName;};//自動(dòng)創(chuàng)建分表的腳本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 數(shù)據(jù)庫(kù)讀寫分離

我們?cè)賮?lái)看看開源框架的基類代碼結(jié)構(gòu)截圖,如下:對(duì)于查詢的基本常用的方法都有一個(gè)isMaster=false的參數(shù),該參數(shù)就是用于是否讀取主庫(kù),用于基本的主從數(shù)據(jù)庫(kù)的分離,也就是讀寫分離,那改怎么配置讀寫分離數(shù)據(jù)庫(kù)呢 鏈接字符串如下圖:分別指定了主從數(shù)據(jù)庫(kù)的鏈接字符串. 我們來(lái)分析源代碼,核心框架源代碼如下:

/// <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>/// 主庫(kù)/// </summary>private string Master{get { return $"{_connNameOfPrefix}{_connNmeOfMaster}"; }}/// <summary>/// 從庫(kù)/// </summary>private string Secondary{get{return $"{_connNameOfPrefix}{_connNameOfSecondary}";}}#endregion/// <summary>/// 獲取鏈接名稱/// </summary>/// <param name="isMaster"></param>/// <param name="store">不能包含點(diǎn)</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;} }

代碼中根據(jù)isMaster 參數(shù)來(lái)進(jìn)行讀寫數(shù)據(jù)庫(kù)鏈接參數(shù)的獲取,以達(dá)到讀寫分離的功能,同時(shí)還支持前綴的配置支持,也開源自由配置多個(gè)數(shù)據(jù)庫(kù)進(jìn)行讀取,只需要構(gòu)造函數(shù)中獲取配置即可。上面的分表Demo 單元測(cè)試運(yùn)行后的結(jié)果例子如下圖:已經(jīng)按照MerchantId 字段進(jìn)行分表

三、總結(jié)

到這里用戶表已經(jīng)根據(jù)商戶ID進(jìn)行分表存儲(chǔ)了,這樣就做到了讀寫分離及自定義分表策略存儲(chǔ)數(shù)據(jù),core-data 開源框架還支持更多的強(qiáng)大功能,實(shí)現(xiàn)了一系列的基礎(chǔ)CRUD的方法,不用寫任何的sql語(yǔ)句,Where表達(dá)式的支持,同時(shí)可以自定義復(fù)雜的sql語(yǔ)句,更多請(qǐng)?jiān)L問框架開源地址:https://github.com/overtly/core-data. 完整的Demo 代碼 已經(jīng)放在github上,Demo代碼結(jié)構(gòu)圖如下:地址:https://github.com/a312586670/NetCoreDemo

原創(chuàng)不易,覺得對(duì)你有幫助請(qǐng)給一個(gè)贊

往期精彩回顧



  • 【.net core】電商平臺(tái)升級(jí)之微服務(wù)架構(gòu)應(yīng)用實(shí)戰(zhàn)

  • .Net Core微服務(wù)架構(gòu)技術(shù)棧的那些事

  • Asp.Net Core 中IdentityServer4 授權(quán)中心之應(yīng)用實(shí)戰(zhàn)

  • Asp.Net Core 中IdentityServer4 授權(quán)中心之自定義授權(quán)模式

  • Asp.Net Core 中IdentityServer4 授權(quán)流程及刷新Token

  • Asp.Net Core 中IdentityServer4 實(shí)戰(zhàn)之 Claim詳解

  • Asp.Net Core 中IdentityServer4 實(shí)戰(zhàn)之角色授權(quán)詳解

  • Asp.Net Core 中間件應(yīng)用實(shí)戰(zhàn)中你不知道的那些事

  • Asp.Net Core Filter 深入淺出的那些事-AOP

  • Asp.Net Core EndPoint 終結(jié)點(diǎn)路由工作原理解讀

  • ASP.NET CORE 內(nèi)置的IOC解讀及使用


??給個(gè)[在看],是對(duì)我最大的支持??

總結(jié)

以上是生活随笔為你收集整理的.net core 基于Dapper 的分库分表开源框架(core-data)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。