NetCore框架WTM的分表分库实现
2022-06-09 06:53
2671 查看
介绍
本期主角:
ShardingCore
一款ef-core下高性能、轻量级针对分表分库读写分离的解决方案,具有零依赖、零学习成本、零业务代码入侵WTM
WalkingTec.Mvvm框架(简称WTM)是基于.net core的快速开发框架。支持Layui(前后端不分离), React(前后端分离),VUE(前后端分离),内置代码生成器,最大程度的提高开发效率,是一款高效开发的利器。
ShardingCore最新版本针对路由有了极大性能的优化由原先的Expression改成自定义的RouteExpression去除了Compile带来的性能损耗
我不是efcore怎么办
这边肯定有小伙伴要问有没有不是efcore的,我这边很确信的和你讲有并且适应所有的ADO.NET包括sqlhelper
ShardingConnector
一款基于ado.net下的高性能分表分库解决方案目前已有demo案例,这个框架你可以认为是.Net版本的
ShardingSphere但是目前仅实现了
ShardingSphere-JDBC,后续我将会实现
ShardingSphere-Proxy希望各位.Neter多多关注
背景
之前我不是发了一篇博客吗.Net分表分库动态化处理 下面有个小伙伴留言,希望可以让我支持一下WTM 框架。我心想着处于对自己的框架的自信,并且之前有过对
abpvnex和
furion等一系列框架的兼容适配的尝试,原则上将只要你是efcore那么基本上都可以支持,所以秉着尝试以下的态度这边就上手了,先说下结论就是可以支持,完美不完美不清楚因为本人这个框架用的不多不知道是否是完美适配。
原理
ShardingCore
ShardingCore的整体架构是一个壳dbcontext带多个dbcontext,壳dbcontext不进行增删改查,由内部的dbcontext自己去执行,这个因为efcore的一个对象对应一个表所限制的。我们这边把壳dbcontext称作
shellDbContext,执行的dbcontext叫做
executorDbContext,对于
ShardingCore还有一个要求就是需要初始化启动的时候
Start(),
Start()内部需要
IServiceProvider来获取
DbContext,所以说整个框架离不开ioc,那么就需要启动的时候依赖注入
DbContext,又因为依赖注入如果是默认的只能允许单个构造函数。这就是
ShardingCore在兼容使用的时候需要注意的地方。
WTM
WTM这边我不是很熟悉,花了大概半个小时到一个小时左右的时间,进行了代码的翻阅,大概了解了其中的实现,DbContext的创建由独立的构造函数来实现,默认通过
DbContext的内部方法
OnConfiguring(DbContextOptionsBuilder optionsBuilder)来进行初始化,框架里面将
DbContext抽象成了
IDataContext接口,框架默
IDataContext接口默认依赖注入为
NullDbContext如果需要使用会自行通过反射调用构造函数参数为
CS类型的那一个。整体的efcore上的一些处理通过调试代码和源码的查看基本上了解了
开始接入
创建项目
那么我们首先通过
WTM生成一个脚手架的简单项目,这边生成了一个mvc的项目。
添加依赖
添加
ShardingCore依赖,需要x.5.0.6+版本,x代表efcore的版本
Install-Package ShardingCore -Version 6.5.0.6
添加抽象分表DbContext
这边和
AbpVNext时候继承一样,因为c#不支持多继承,好在
ShardingCore是接口依赖不存在实现依赖所以任何框架都可以兼容。
public abstract class AbstractShardingFrameworkContext:FrameworkContext, IShardingDbContext, ISupportShardingReadWrite { protected IShardingDbContextExecutor ShardingDbContextExecutor { get; } public AbstractShardingFrameworkContext(CS cs) : base(cs) { ShardingDbContextExecutor = (IShardingDbContextExecutor)Activator.CreateInstance( typeof(ShardingDbContextExecutor<>).GetGenericType0(this.GetType()),this); IsExecutor = false; } public AbstractShardingFrameworkContext(string cs, DBTypeEnum dbtype) : base(cs, dbtype) { ShardingDbContextExecutor = (IShardingDbContextExecutor)Activator.CreateInstance( typeof(ShardingDbContextExecutor<>).GetGenericType0(this.GetType()),this); IsExecutor = false; } public AbstractShardingFrameworkContext(string cs, DBTypeEnum dbtype, string version = null) : base(cs, dbtype, version) { ShardingDbContextExecutor = (IShardingDbContextExecutor)Activator.CreateInstance( typeof(ShardingDbContextExecutor<>).GetGenericType0(this.GetType()),this); IsExecutor = false; } public AbstractShardingFrameworkContext(DbContextOptions options) : base(options) { var wrapOptionsExtension = options.FindExtension<ShardingWrapOptionsExtension>(); if (wrapOptionsExtension != null) { ShardingDbContextExecutor = (IShardingDbContextExecutor)Activator.CreateInstance( typeof(ShardingDbContextExecutor<>).GetGenericType0(this.GetType()),this); } IsExecutor = wrapOptionsExtension == null; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { if (this.CSName!=null) { base.OnConfiguring(optionsBuilder); optionsBuilder.UseSharding<DataContext>(); } } }
简单说一下这边实现了
WTM的所有构造函数,因为ShardingCore原生需要
DbContextOption,当然也是可以支持实现类由自定义
DbContext,构造函数中如果使用了
DbContextOption那么就是由依赖注入或者
ShardingCore创建的
DbContext,其余的全部是
WTM创建的,所以这边都需要实现并且其余的构造函数直接设置为
ShellDbContext
又因为
WTM默认的创建会赋值
CSName所以需要对其后续进行
UseSharding处理这是
ShardingCore针对
ShellDbContext必须要处理的
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { if (this.CSName!=null) { base.OnConfiguring(optionsBuilder); optionsBuilder.UseSharding<DataContext>(); } }
实现DataContext
很简单只需要继承抽象类和实现
IShardingTableDbContext接口即可,实现该接口才能支持分表否则仅支持分库
public class DataContext : AbstractShardingFrameworkContext,IShardingTableDbContext { }
编写自定义DbContext创建
因为
WTM框架的
DbContext拥有多个构造函数所以需要自定义,由
ShardingCore提供
代码其实很简单就是如何创建一个
DbContext,因为
ShardingCore默认的会校验只能拥有一个构造函数并且构造函数只能是
DbContextOptions或者
DbContextOptions<>
public class WTMDbContextCreator<TShardingDbContext>:IDbContextCreator<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext { public DbContext CreateDbContext(DbContext shellDbContext, ShardingDbContextOptions shardingDbContextOptions) { var context = new DataContext((DbContextOptions<DataContext>)shardingDbContextOptions.DbContextOptions); context.RouteTail = shardingDbContextOptions.RouteTail; return context; } }
编写分表测试类
public class Todo { public string Id { get; set; } public string Name { get; set; } }
然后再
DbContext出简单设置一下
protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); //你用dbset也是可以的 modelBuilder.Entity<Todo>(e => { e.HasKey(o => o.Id); e.ToTable(nameof(Todo)); }); }
添加分表路由
public class TodoRoute:AbstractSimpleShardingModKeyStringVirtualTableRoute<Todo> { public TodoRoute() : base(2, 10) { } public override void Configure(EntityMetadataTableBuilder<Todo> builder) { builder.ShardingProperty(o => o.Id); } }
StartUp
接下来就是激动人心的时候了,首先我们说过
ShardingCore需要依赖注入,由因为
DbContext是多构造函数
services.AddScoped<DataContext>(sp => { var dbContextOptionsBuilder = new DbContextOptionsBuilder<DataContext>(); dbContextOptionsBuilder.UseMySql( "server=127.0.0.1;port=3306;database=shardingTest;userid=root;password=root;", new MySqlServerVersion(new Version())); dbContextOptionsBuilder.UseSharding<DataContext>(); return new DataContext(dbContextOptionsBuilder.Options); });
注意依赖注入获取的是ShellDbContext所以我们需要对其进行UseSharding()
再来我们需要配置ShardingCore
services.AddShardingConfigure<DataContext>() .AddEntityConfig(o => { o.CreateShardingTableOnStart = true; o.EnsureCreatedWithOutShardingTable = true; o.AddShardingTableRoute<TodoRoute>(); }) .AddConfig(o => { o.AddDefaultDataSource("ds0", "server=127.0.0.1;port=3306;database=shardingTest;userid=root;password=root;"); o.ConfigId = "c1"; o.UseShardingQuery((conn, build) => { build.UseMySql(conn, new MySqlServerVersion(new Version())).UseLoggerFactory(efLogger); }); o.UseShardingTransaction((conn,build)=> build.UseMySql(conn,new MySqlServerVersion(new Version())).UseLoggerFactory(efLogger) ); o.ReplaceTableEnsureManager(sp => new MySqlTableEnsureManager<DataContext>()); }).EnsureConfig();
这边的配置就是
ShardingCore很简单可以查询文档或者过往的博客
这个时候有人要说了为什么不使用
AddShardingDbContext因为多构造函数默认不支持需要手动处理。
替换
ShardingCore的
DbContext创建,我们刚才写的
services.Replace(ServiceDescriptor.Singleton<IDbContextCreator<DataContext>, WTMDbContextCreator<DataContext>>());
再然后替换
WTM的
IDataContext
//这是WTM的默认的需要替换掉 //services.TryAddScoped<IDataContext, NullContext>(); services.Replace(ServiceDescriptor.Scoped<IDataContext>(sp => { return sp.GetService<DataContext>(); }));
然后启动初始化ShardingCore
app.ApplicationServices.GetRequiredService<IShardingBootstrapper>().Start();
编写测试demo
public async Task<ActionResult> Login(LoginVM vm) { var dataContext = Wtm.DC; var todos = new List<Todo>(); for (int i = 0; i < 100; i++) { var todo = new Todo(); todo.Id = Guid.NewGuid().ToString("n"); todo.Name = todo.Id; todos.Add(todo); } await dataContext.Set<Todo>().AddRangeAsync(todos); await dataContext.SaveChangesAsync(); var listAsync = await dataContext.Set<Todo>().Take(2).ToListAsync(); .... }
启动运行
完美创建分表并且可以插入查询完全和使用
WTM一样
最后的最后
demo地址 https://github.com/xuejmnet/ShardingWTM
您都看到这边了确定不点个star或者赞吗,一款.Net不得不学的分库分表解决方案,简单理解为sharding-jdbc在.net中的实现并且支持更多特性和更优秀的数据聚合,拥有原生性能的97%,并且无业务侵入性,支持未分片的所有efcore原生查询
相关文章推荐
- efcore使用ShardingCore实现分表分库下的多租户
- .NET Core实现分表分库、读写分离的通用 Repository功能
- 【数据库中间件】MyCat分表分库规则实现
- 数据库分库分表策略的具体实现方案
- SpringCloud实现分库分表模式下,数据库实时扩容方案
- 京东一元抢宝业务分库分表实现策略
- SpringBoot 2.0 整合sharding-jdbc中间件实现数据分库分表
- ubuntu系统下使用mycat实现分库分表(二)使用本地文件处理主键自增长
- 数据库分库分表策略的具体实现方案
- SpringBoot 2.0 整合sharding-jdbc中间件,实现数据分库分表
- MyCat分表分库规则实现
- 分库分表策略的可实现架构
- 170123、数据库分库分表策略的具体实现方案
- sharding jdbc + mybatis +spring boot的分库分表实现
- Spring MVC +Spring + Mybatis 构建分库分表总结 SSM搭建以及分库分表的实现
- 分库分表时用Redis自增实现计数实现分布式id
- 详解yii2实现分库分表的方案与思路
- Sharding-jdbc实现分库分表
- MySQL 高可用:mysql+mycat实现数据库分片(分库分表)
- 主从的搭建+shell实现检测并邮件报警。 数据库分库分表备份+任务定时计划