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