efcore根据多个条件更新_EFCore.Sharding(EFCore开源分表框架)
簡介
本框架旨在為EF Core提供Sharding(即讀寫分離分庫分表)支持,不僅提供了一套強(qiáng)大的普通數(shù)據(jù)操作接口,并且降低了分表難度,支持按時間自動分表擴(kuò)容,提供的操作接口簡潔統(tǒng)一.
源碼地址:EFCore.SHarding
引言
讀寫分離分庫分表一直是數(shù)據(jù)庫領(lǐng)域中的重難點(diǎn),當(dāng)數(shù)據(jù)規(guī)模達(dá)到單庫極限的時候,就不得不考慮分表方案。EF Core作為.NET Core中最為主流的ORM,用起來十分方便快捷,但是官方并沒有相應(yīng)的Sharding支持,鄙人不才,經(jīng)過一番摸索之后終于完成這個框架.
開始
準(zhǔn)備
首先根據(jù)需要安裝對應(yīng)的Nuget包
包名說明EFCore.Sharding必裝包,3.x版本對應(yīng)EF Core3.x,2.x版本對應(yīng)EF Core2.xEFCore.Sharding.MySqlMySql支持EFCore.Sharding.PostgreSqlPostgreSql支持EFCore.Sharding.SQLiteSQLite支持EFCore.Sharding.SqlServerSqlServer支持EFCore.Sharding.OracleOracle支持(暫不支持3.x)
配置
class Base_UnitTestShardingRule : ModShardingRule{ protected override string KeyField => "Id"; protected override int Mod => 3;}ShardingConfig.Init(config =>{ config.AddAbsDb(DatabaseType.SQLite) .AddPhysicDb(ReadWriteType.Read | ReadWriteType.Write, "DataSource=db.db") .AddPhysicDbGroup() .AddPhysicTable("Base_UnitTest_0") .AddPhysicTable("Base_UnitTest_1") .AddPhysicTable("Base_UnitTest_2") .SetShardingRule(new Base_UnitTestShardingRule());});上述代碼中完成了Sharding配置
- AddAbsDb是指添加抽象數(shù)據(jù)庫,抽象數(shù)據(jù)庫就是將多個分庫看成同一個數(shù)據(jù)庫來進(jìn)行操作
- AddPhysicDbGroup是指添加物理數(shù)據(jù)庫組,在同一組物理數(shù)據(jù)庫中,它們數(shù)據(jù)庫類型相同,擁有的表相同,每個數(shù)據(jù)庫擁有的數(shù)據(jù)是一致的(之間通過主主復(fù)制或主從復(fù)制進(jìn)行數(shù)據(jù)同步)
- AddPhysicTable是指添加物理數(shù)據(jù)表,傳入的Base_UnitTest是抽象數(shù)據(jù)表(即將Base_UnitTest拆分為Base_UnitTest_0~2)
- Base_UnitTestShardingRule是采用的分表規(guī)則,上述代碼中采用的是哈希取模的分表方式
使用
配置完成,下面開始使用,使用方式非常簡單,與平常使用基本一致首先獲取分片倉儲接口IShardingRepository
IShardingRepository _db = DbFactory.GetRepository().ToSharding();然后即可進(jìn)行數(shù)據(jù)操作:
Base_UnitTest _newData = new Base_UnitTest{ Id = Guid.NewGuid().ToString(), UserId = "Admin", UserName = "超級管理員", Age = 22};List _insertList = new List{ new Base_UnitTest { Id = Guid.NewGuid().ToString(), UserId = "Admin1", UserName = "超級管理員1", Age = 22 }, new Base_UnitTest { Id = Guid.NewGuid().ToString(), UserId = "Admin2", UserName = "超級管理員2", Age = 22 }};//添加單條數(shù)據(jù)_db.Insert(_newData);//添加多條數(shù)據(jù)_db.Insert(_insertList);//清空表_db.DeleteAll();//刪除單條數(shù)據(jù)_db.Delete(_newData);//刪除多條數(shù)據(jù)_db.Delete(_insertList);//刪除指定數(shù)據(jù)_db.Delete(x => x.UserId == "Admin2");//更新單條數(shù)據(jù)_db.Update(_newData);//更新多條數(shù)據(jù)_db.Update(_insertList);//更新單條數(shù)據(jù)指定屬性_db.UpdateAny(_newData, new List { "UserName", "Age" });//更新多條數(shù)據(jù)指定屬性_db.UpdateAny(_insertList, new List { "UserName", "Age" });//更新指定條件數(shù)據(jù)_db.UpdateWhere(x => x.UserId == "Admin", x =>{ x.UserId = "Admin2";});//GetList獲取表的所有數(shù)據(jù)var list=_db.GetList();//GetIQPagination獲取分頁后的數(shù)據(jù)var list=_db.GetIShardingQueryable().GetPagination(pagination);//Maxvar max=_db.GetIShardingQueryable().Max(x => x.Age);//Minvar min=_db.GetIShardingQueryable().Min(x => x.Age);//Averagevar min=_db.GetIShardingQueryable().Average(x => x.Age);//Countvar min=_db.GetIShardingQueryable().Count();//事務(wù),使用方式與普通事務(wù)一致bool succcess = _db.RunTransaction(() =>{ _db.Insert(_newData); var newData2 = _newData.DeepClone(); _db.Insert(newData2);}).Success;Assert.AreEqual(succcess, false);上述操作中表面上是操作Base_UnitTest表,實(shí)際上卻在按照一定規(guī)則使用Base_UnitTest_0~2三張表,使分片對業(yè)務(wù)操作透明,極大提高開發(fā)效率具體使用方式請參考單元測試源碼:連接
按時間自動分表
上面的哈希取模的方式雖然簡單,但是卻十分不實(shí)用,因為當(dāng)3張分表到達(dá)瓶頸時,將會面臨擴(kuò)容的問題,這種方式擴(kuò)容需要進(jìn)行大量的數(shù)據(jù)遷移,這無疑是十分麻煩的。因此需要一種方式能夠系統(tǒng)自動建表擴(kuò)容,并且無需人工干預(yù),這就是按時間自動分表.
using Demo.Common;using EFCore.Sharding;using System;using System.Collections.Generic;using System.Threading;using System.Threading.Tasks;namespace Demo.AutoExpandByDate{ class Base_UnitTestShardingRule : AbsShardingRule { public override DateTime BuildDate(Base_UnitTest obj) { return obj.CreateTime; } } class Program { /// /// 表都在同一個數(shù)據(jù)庫中 /// public static void OneGroup() { DateTime startTime = DateTime.Now.AddMinutes(-5); DateTime endTime = DateTime.MaxValue; //配置初始化 ShardingConfig.Init(config => { config.AddAbsDb(DatabaseType.SqlServer)//添加抽象數(shù)據(jù)庫 .AddPhysicDbGroup()//添加物理數(shù)據(jù)庫組 .AddPhysicDb(ReadWriteType.Read | ReadWriteType.Write, Config.ConString1)//添加物理數(shù)據(jù)庫1 .SetShardingRule(new Base_UnitTestShardingRule())//設(shè)置分表規(guī)則 .AutoExpandByDate(//設(shè)置為按時間自動分表 ExpandByDateMode.PerMinute, (startTime, endTime, ShardingConfig.DefaultDbGourpName) ); }); var db = DbFactory.GetShardingRepository(); while (true) { db.Insert(new Base_UnitTest { Id = Guid.NewGuid().ToString(), Age = 1, UserName = Guid.NewGuid().ToString(), CreateTime = DateTime.Now }); var count = db.GetIShardingQueryable().Count(); Console.WriteLine($"當(dāng)前數(shù)據(jù)量:{count}"); Thread.Sleep(50); } } /// /// 表分布在兩個數(shù)據(jù)庫測試 /// public static void TwoGroup() { DateTime startTime1 = DateTime.Now.AddMinutes(-5); DateTime endTime1 = DateTime.Now.AddMinutes(5); DateTime startTime2 = endTime1; DateTime endTime2 = DateTime.MaxValue; string group1 = "group1"; string group2 = "group2"; //配置初始化 ShardingConfig.Init(config => { config.AddAbsDb(DatabaseType.SqlServer)//添加抽象數(shù)據(jù)庫 .AddPhysicDbGroup(group1)//添加物理數(shù)據(jù)庫組1 .AddPhysicDbGroup(group2)//添加物理數(shù)據(jù)庫組2 .AddPhysicDb(ReadWriteType.Read | ReadWriteType.Write, Config.ConString1, group1)//添加物理數(shù)據(jù)庫1 .AddPhysicDb(ReadWriteType.Read | ReadWriteType.Write, Config.ConString2, group2)//添加物理數(shù)據(jù)庫2 .SetShardingRule(new Base_UnitTestShardingRule())//設(shè)置分表規(guī)則 .AutoExpandByDate(//設(shè)置為按時間自動分表 ExpandByDateMode.PerMinute, (startTime1, endTime1, group1), (startTime2, endTime2, group2) ); }); List tasks = new List(); for (int i = 0; i < 4; i++) { tasks.Add(Task.Run(() => { var db = DbFactory.GetShardingRepository(); while (true) { db.Insert(new Base_UnitTest { Id = Guid.NewGuid().ToString(), Age = 1, UserName = Guid.NewGuid().ToString(), CreateTime = DateTime.Now }); var count = db.GetIShardingQueryable().Count(); Console.WriteLine($"當(dāng)前數(shù)據(jù)量:{count}"); Thread.Sleep(50); } })); } Console.ReadLine(); } static void Main(string[] args) { OneGroup(); Console.ReadLine(); } }}上面Demo都在源碼中
上面的代碼實(shí)現(xiàn)了將Base_UnitTest表按照時間自動分表,每分鐘創(chuàng)建一張表,實(shí)際使用中根據(jù)業(yè)務(wù)需求設(shè)置ExpandByDateMode參數(shù),常用按天、按月分表
自動分表效果
全程無需人工干預(yù),系統(tǒng)會自動定時創(chuàng)建分表,十分簡單好用
性能測試
using Demo.Common;using EFCore.Sharding;using System;using System.Diagnostics;using System.Linq;namespace Demo.Performance{ class Base_UnitTestShardingRule : ModShardingRule { protected override string KeyField => "Id"; protected override int Mod => 3; } class Program { static void Main(string[] args) { ShardingConfig.Init(config => { config.AddAbsDb(DatabaseType.SqlServer) .AddPhysicDb(ReadWriteType.Read | ReadWriteType.Write, Config.ConString1) .AddPhysicDbGroup() .AddPhysicTable("Base_UnitTest_0") .AddPhysicTable("Base_UnitTest_1") .AddPhysicTable("Base_UnitTest_2") .SetShardingRule(new Base_UnitTestShardingRule()); }); var db = DbFactory.GetRepository(Config.ConString1, DatabaseType.SqlServer); Stopwatch watch = new Stopwatch(); var q = db.GetIQueryable() .Where(x => x.UserName.Contains("00001C22-8DD2-4D47-B500-407554B099AB")) .OrderByDescending(x => x.Id) .Skip(0) .Take(30); q.ToList(); q.ToSharding().ToList(); watch.Restart(); var list1 = q.ToList(); watch.Stop(); Console.WriteLine($"未分表耗時:{watch.ElapsedMilliseconds}ms"); watch.Restart(); var list2 = q.ToSharding().ToList(); watch.Stop(); Console.WriteLine($"分表后耗時:{watch.ElapsedMilliseconds}ms"); Console.WriteLine("完成"); } }}分表Base_UnitTest_0-2各有100萬數(shù)據(jù),然后將這三張表的數(shù)據(jù)導(dǎo)入Base_UnitTest中(即Base_UnitTest表的數(shù)據(jù)與Base_UnitTest_0-2三張表總合數(shù)據(jù)一致)
分表與不分表測試結(jié)果如下
這里僅僅分了3張表,其效果立桿見影,若分表幾十張,那效果想想就很棒
其它簡單操作(非Sharing)
框架不僅支持Sharing,而且封裝了常用數(shù)據(jù)庫操作,使用比較簡單詳細(xì)使用方式參考 鏈接
總結(jié)
這個簡單實(shí)用強(qiáng)大的框架希望能夠幫助到大家,力求為.NET生態(tài)貢獻(xiàn)一份力,大家一起壯大.NET生態(tài)
歡迎使用本框架,若覺得不錯,請比心
Github歡迎星星:https://github.com/Coldairarrow
博客園歡迎點(diǎn)贊:https://www.cnblogs.com/coldairarrow/
總結(jié)
以上是生活随笔為你收集整理的efcore根据多个条件更新_EFCore.Sharding(EFCore开源分表框架)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux adb工具_这是一个可以显示
- 下一篇: symantec 操作 重叠vo_无关收