ShardingCore
是一個支持efcore 2.x 3.x 5.x的一個對於數據庫分表的一個簡易擴展,固然也支持不分表的普通使用,.Net下並無相似mycat或者sharding-jdbc之類的開源組件或者說有可是並無很是適用的或者說我的在用事後有一些地方由於限制無法很好使用因此決定本身開發這個庫,目前該庫暫未支持分庫(將來會支持),僅支持分表,該項目的理念是讓你能夠已最少的代碼量來實現自動分表的實現,通過多個開源項目的摸索參考目前正式開源本項目
項目地址 github 喜歡的朋友能夠點下star Thanks♪(・ω・)ノgit
Release | EF Core | .NET Standard | .NET (Core) | Sql Server | Pomelo.EntityFrameworkCore.MySql |
---|---|---|---|---|---|
5.x.x.x | >= 5.0.x | 2.1 | 3.0+ | >= 2012 | 5.0.0-alpha.2 |
3.x.x.x | 3.1.10 | 2.0 | 2.0+ | >= 2012 | 3.2.4 |
2.x.x.x | 2.2.6 | 2.0 | 2.0+ | >= 2008 | 2.2.6 |
如下全部例子都以Sql Server爲例 MySql亦如此github
目前該庫處於初期階段,有不少bug也但願各位多多理解,一塊兒努力爲.net生態作出一份微薄之力,目前該庫支持的分表能夠進行徹底的自定義,基本上能夠知足95%以上的
業務需求,惟一的限制就是分表規則必須知足 x+y+z,x表示固定的表名,y表示固定的表名和表後綴之間的聯繫(能夠爲空),z表示表後綴,能夠按照你本身的任意業務邏輯進行切分,
如:user_0,user_1或者user202101,user202102...固然該庫一樣適用於多租戶模式下的隔離,該庫爲了支持以後的分庫已經重寫了以前的union all查詢模式,而且支持多種api,
支持多種查詢包括join,group by,max,count,min,avg,sum
...等一系列查詢,以後可能會添加更多支持,目前該庫的使用很是簡單,基本上就是針對IQueryable的擴展,爲了保證
該庫的簡介目前僅使用該庫沒法或者說難以實現自動建表,可是隻須要配合定時任務該庫便可完成24小時無人看管自動管理。該庫提供了 IShardingTableCreator
做爲建表的依賴,若是須要能夠參考 按天自動建表數據庫
本庫的幾個簡單的核心概念:c#
join
BulkInsert、BulkUpdate、BulkDelete
AbstractShardingOperatorVirtualRoute<T, TKey>
)笛卡爾積
致使鏈接數爆炸,後期會進行鍼對該狀況的配置<PackageReference Include="ShardingCore.SqlServer" Version="5.0.0.4" />
配置entity 推薦 fluent api 能夠實現自動建表功能
IShardingEntity
數據庫對象必須繼承該接口
ShardingKey
分表字段須要使用該特性api
public class SysUserMod:IShardingEntity { /// <summary> /// 用戶Id用於分表 /// </summary> [ShardingKey] public string Id { get; set; } /// <summary> /// 用戶名稱 /// </summary> public string Name { get; set; } /// <summary> /// 用戶姓名 /// </summary> public int Age { get; set; } } public class SysUserModMap:IEntityTypeConfiguration<SysUserMod> { public void Configure(EntityTypeBuilder<SysUserMod> builder) { builder.HasKey(o => o.Id); builder.Property(o => o.Id).IsRequired().HasMaxLength(128); builder.Property(o => o.Name).HasMaxLength(128); builder.ToTable(nameof(SysUserMod)); } }
建立virtual route
實現 AbstractShardingOperatorVirtualRoute<T, TKey>
抽象,或者實現系統默認的虛擬路由
框架默認有提供幾個簡單的路由 默認路由app
public class SysUserModVirtualRoute : AbstractSimpleShardingModKeyStringVirtualRoute<SysUserMod> { public SysUserModVirtualRoute() : base(3) { } }
GetAllTails
Startup.cs
下的 ConfigureServices(IServiceCollection services)
框架
services.AddShardingSqlServer(o => { o.ConnectionString = ""; o.AddSharding<SysUserModVirtualRoute>(); o.UseShardingCoreConfig((provider, config) => { //若是是development就判斷而且新建數據庫若是不存在的話(ishardingentity不會被建立) config.EnsureCreated = provider.GetService<IHostEnvironment>().IsDevelopment(); //ishardingentity表是否須要在啓動時建立(若是已建立能夠選擇不建立) config.CreateShardingTableOnStart = true; }); });
Startup.cs
下的 Configure(IApplicationBuilder app, IWebHostEnvironment env)
你也能夠自行封裝app.UseShardingCore()async
var shardingBootstrapper = app.ApplicationServices.GetRequiredService<IShardingBootstrapper>(); shardingBootstrapper.Start();
private readonly IVirtualDbContext _virtualDbContext; public ctor(IVirtualDbContext virtualDbContext) { _virtualDbContext = virtualDbContext; } public async Task ToList_All() { //查詢list集合 var all=await _virtualDbContext.Set<SysUserMod>().ToShardingListAsync(); //連接查詢 var list = await (from u in _virtualDbContext.Set<SysUserMod>() join salary in _virtualDbContext.Set<SysUserSalary>() on u.Id equals salary.UserId select new { Salary = salary.Salary, DateOfMonth = salary.DateOfMonth, Name = u.Name }).ToShardingListAsync(); //聚合查詢 var ids = new[] {"200", "300"}; var dateOfMonths = new[] {202111, 202110}; var group = await (from u in _virtualDbContext.Set<SysUserSalary>() .Where(o => ids.Contains(o.UserId) && dateOfMonths.Contains(o.DateOfMonth)) group u by new { UId = u.UserId } into g select new { GroupUserId = g.Key.UId, Count = g.Count(), TotalSalary = g.Sum(o => o.Salary), AvgSalary = g.Average(o => o.Salary), MinSalary = g.Min(o => o.Salary), MaxSalary = g.Max(o => o.Salary) }).ToShardingListAsync(); }
更多操做能夠參考單元測試ide
方法 | Method | SqlServer Unit Test | MySql Unit Test |
---|---|---|---|
獲取集合 | ToShardingListAsync | yes | yes |
第一條 | ShardingFirstOrDefaultAsync | yes | yes |
最大 | ShardingMaxAsync | yes | yes |
最小 | ShardingMinAsync | yes | yes |
是否存在 | ShardingAnyAsync | yes | yes |
分頁 | ToShardingPageResultAsync | yes | yes |
數目 | ShardingCountAsync | yes | yes |
求和 | ShardingSumAsync | yes | yes |
分組 | ShardingGroupByAsync | yes | yes |
抽象abstract | 路由規則 | tail | 索引 |
---|---|---|---|
AbstractSimpleShardingModKeyIntVirtualRoute | 取模 | 0,1,2... | = |
AbstractSimpleShardingModKeyStringVirtualRoute | 取模 | 0,1,2... | = |
AbstractSimpleShardingDayKeyDateTimeVirtualRoute | 按時間 | yyyyMMdd | >,>=,<,<=,=,contains |
AbstractSimpleShardingDayKeyLongVirtualRoute | 按時間戳 | yyyyMMdd | >,>=,<,<=,=,contains |
AbstractSimpleShardingWeekKeyDateTimeVirtualRoute | 按時間 | yyyyMMdd_dd | >,>=,<,<=,=,contains |
AbstractSimpleShardingWeekKeyLongVirtualRoute | 按時間戳 | yyyyMMdd_dd | >,>=,<,<=,=,contains |
AbstractSimpleShardingMonthKeyDateTimeVirtualRoute | 按時間 | yyyyMM | >,>=,<,<=,=,contains |
AbstractSimpleShardingMonthKeyLongVirtualRoute | 按時間戳 | yyyyMM | >,>=,<,<=,=,contains |
AbstractSimpleShardingYearKeyDateTimeVirtualRoute | 按時間 | yyyy | >,>=,<,<=,=,contains |
AbstractSimpleShardingYearKeyLongVirtualRoute | 按時間戳 | yyyy | >,>=,<,<=,=,contains |
注:contains
表示爲o=>ids.contains(o.shardingkey)
單元測試
批量操做將對應的dbcontext和數據進行分離由用戶本身選擇第三方框架好比zzz進行批量操做或者batchextension
virtualDbContext.BulkInsert<SysUserMod>(new List<SysUserMod>()) .BatchGroups.ForEach(pair => { ///zzz or other pair.Key.BlukInsert(pair.Value); }); var shardingBatchUpdateEntry = virtualDbContext.BulkUpdate<SysUserMod>(o => o.Id == "1", o => new SysUserMod() { Name = "name_01" }); shardingBatchUpdateEntry.DbContexts.ForEach(context => { //zzz or other context.Where(shardingBatchUpdateEntry.Where).Update(shardingBatchUpdateEntry.UpdateExp); });
var shardingQueryable = _virtualDbContext.Set<SysUserMod>().AsSharding(); //禁用自動路由 shardingQueryable.DisableAutoRouteParse(); //添加路由直接查詢尾巴0的表 shardingQueryable.AddManualRoute<SysUserMod>("0"); //添加路由針對該條件的路由 shardingQueryable.AddManualRoute<SysUserMod>(o=>o.Id=="100"); var list=await shardingQueryable.ToListAsync();
默認savechanges支持事務若是須要where.update須要手動開啓事務
_virtualDbContext.BeginTransaction(); var shardingBatchUpdateEntry = _virtualDbContext.BulkUpdate<SysUserMod>(o=>o.Id=="123",o=>new SysUserMod() { Name = "name_modify" }); foreach (var dbContext in shardingBatchUpdateEntry.DbContexts) { //zzz or other batch } await _virtualDbContext.SaveChangesAsync();
該庫的IVirtualDbContext.Set
可能會致使程序集未被加載因此儘量在api層加載所須要的dll
使用時須要注意
IShardingEntity
ShardingKey
services.AddShardingSqlServer(o => { o.ConnectionString = ""; o.AddSharding<SysUserModVirtualRoute>(); o.UseShardingCoreConfig((provider, config) => { //若是是development就判斷而且新建數據庫若是不存在的話(ishardingentity不會被建立) config.EnsureCreated = provider.GetService<IHostEnvironment>().IsDevelopment(); //ishardingentity表是否須要在啓動時建立(若是已建立能夠選擇不建立) config.CreateShardingTableOnStart = true; }); });
var shardingBootstrapper = app.ApplicationServices.GetRequiredService<IShardingBootstrapper>(); shardingBootstrapper.Start();
理論上該庫的思想能夠解決大部分orm的分表,目前是僅針對efcore的後期若是能夠獲取也會對其餘orm進行sharding庫的開發
該框架借鑑了大部分分表組件的思路,目前提供的接口都已經實現,而且支持跨表查詢,基於分頁查詢該框架也使用了流式查詢保證不會再skip大數據的時候內存會爆炸,至於groupby目前已經在開發支持了,相信不久後就會發布新版本,目前這個庫只是一個剛剛成型的庫還有不少不完善的地方但願你們多多包涵,若是喜歡的話也但願你們給個star.
該文檔是我晚上趕工趕出來的也想趁熱打鐵但願更多的人關注,也但願更多的人能夠交流。
憑藉各大開源生態圈提供的優秀代碼和思路纔有的這個框架,但願能夠爲.Net生態提供一份微薄之力,該框架本人會一直長期維護,有大神技術支持能夠聯繫下方方式歡迎star 😃
QQ羣:771630778
我的QQ:326308290(歡迎技術支持提供您寶貴的意見)
我的郵箱:326308290@qq.com