电商网站开发数据库设计,微信网站和手机网站的区别,微信小程序注册账号,小程序开发接单ShardingCore 易用、简单、高性能、普适性#xff0c;是一款扩展针对efcore生态下的分表分库的扩展解决方案,支持efcore2的所有版本,支持efcore2的所有数据库、支持自定义路由、动态路由、高性能分页、读写分离的一款组件#xff0c;如果你喜欢这组件或者这个组件对你有帮助请… ShardingCore 易用、简单、高性能、普适性是一款扩展针对efcore生态下的分表分库的扩展解决方案,支持efcore2的所有版本,支持efcore2的所有数据库、支持自定义路由、动态路由、高性能分页、读写分离的一款组件如果你喜欢这组件或者这个组件对你有帮助请点击下发star让更多的.neter可以看到使用Gitee Star 助力dotnet 生态 Github Star背景你是否在使用efcore,你是否在使用abp你是否对目前的分表十分厌恶手动指定表让你的代码无辜多出很多胶水代码那么这次的文章可以很好的帮你解决掉当前的困难点sharding-core 针对efcore的分库分表读写分离的痛点进行扩展,可以完美集成到efcore生态的系统里面,无论你是abp还是其他使用efcore的框架,你确定真的不看一下吗,如何集成abp当时我发布这个库的时候就有很多人问我是否支持我的回答是支持的只是个人没有时间去实现。这次已经实现了我这边将分享下如何集成sharding-core到abp vnext中。距离上一篇博客已经两周了在这两周期间本人还是做了很多事情针对优化sharding-core的使用和体验就在上周五傍晚的时候有个使用abp的同学联系我问我什么时候支持abp vnext其实这个计划我很早之前就在issue里面备注了只是获取用abp的同学没有怎么关注这个类库也没人提出来所以就搁置了。因为sharding-core是一款几乎可以说可以集成到任何efcore生态下的所以原则上abp上集成应该是没什么难度的因为本人使用abp不是很多所以这边自己按官方教程进行了初步的项目搭建然后又用了一会功夫了解了abp源码(之前有了解过)清楚了dbcontext的创建过程所以很快就继承好了一个todoapp接下来我将用一篇博客的篇幅来介绍如何将sharing-core集成到abp vnext中。如何集成abp项目创建/下载我这边是通过github进行了例子的todoapp 进行下载,下载后是一个集合例子我们获取TodoApp项目进行单独处理打开然后编译。注意如果你自己会新建那么也是一样的集成abp思路用过abp的用户都应该知道abp的dbcontext没有什么不一样唯一需要注意的就是abp:只要你的dbcontext继承至 public class TDbContext:AbpDbContextTDbContext那么就可以完美使用.但是sharding-core的使用我们通过readme来查看发现sharidng-core:只要你的dbcontext继承至public class TDbContext:AbstractShardingDbContext那么你就可以完美使用.好家伙直接给想自己集成的同学搞蒙蔽了c#又不是c艹没有多继承啊那怎么办但是这边其实是有一个误区的就是abp确实需要继承abpdbcontext但是sharding-core是已接口作为依赖来开发的所以我们只需要实现ISharingDbContext 这个接口就可以了如果需要事务在实现ISupportShardingTransaction最终我们是通过实现一个抽象基类来继承abpdbcntext并且实现sharding-core需要的接口 AbstractShardingAbpDbContext 这样我们就可以在不破坏abp的同时又兼顾了sharding-core注意这边sharing-core让你们继承AbstractShardingDbContext是因为重复写这些接口的实现会很麻烦所以给你们写了一个抽象方便你们使用abp集成注意事项通过源码可以看出abp集成需要赋值lazyserviceprovider 因为abp的dbcontext是交由uow自己处理并且需要支持很多特性所以我们在创建dbcontext的时候需要对此处进行赋值注意点。注意abp默认提供了IEntityGuid,IHasCreationTime属性较为常用所以我们需要注意如何支持这两种因为当你用id取模分表或者创建时间分表的使用场景还是比较常见的所以我们需要支持。因为在insert时如果sharding-core发现对应的分表字段为null就无法继续执行下去所以为了兼容abp需要支持两个比较常见的需求赋值依赖注入支持domain event等事件自动属性了解sahrding-core针对dbcontext的分表支持首先我们需要知道sharding-core是如何对一个普通的dbcontext进行支持的如果你的dbcontext有用到以下任意一个接口那么集成起来可能需要自己去实现对应的接口IDbSetSource 用来接管dbsetIQueryCompiler 用来接管查询编译IDbContextTransactionManager 用来接管事务开启IRelationalTransactionFactory 用来接管事务的提交、回滚 和加入IModelCacheKeyFactory 用来接管dbcontext的模型缓存IModelCustomizer 用来接管dbcontext的模型初始化前后自定义如果你的efcore想接入sharding-core并且如果你没有对dbcontext的上述任何接口进行替换那么可以很容易就接入如果你的efcore在创建的时候有针对上述的接口进行替换就需要你自己手动进行两边的实现合并。如何接入sharding-core这边我们假设你没有对上述的dbcontextoptionbuilder的创建进行接口的替换那么你只需要进行如下操作就可以简单接入sharding-core首先就是默认创建dbcontext替换为sharding-core的配置原先:public void ConfigureServices(IServiceCollection services)services.AddDbContextDefaultShardingTableDbContext(o o.UseSqlServer(Server.;DatabaseTodoApp;Trusted_ConnectionTrue));现在:public void ConfigureServices(IServiceCollection services)//1.先检查dbcontext构造函数只允许 DbContextOptionsTodoAppDbContext optionsShardingCoreHelper.CheckContextConstructorsDefaultShardingTableDbContext();
//2.添加UseShardingDefaultShardingTableDbContext()让依赖注入创建的dbcontext支持查询插入事务的管理services.AddDbContextDefaultShardingTableDbContext(oo.UseSqlServer(Server.;DatabaseTodoApp;Trusted_ConnectionTrue).UseShardingDefaultShardingTableDbContext());
//3.添加分表配置new ShardingCoreConfigBuilderDefaultShardingTableDbContext(context.Services,((s, builder) {builder.UseSqlServer(s);} )).Begin(o {o.CreateShardingTableOnStart false;o.EnsureCreatedWithOutShardingTable false;o.AutoTrackEntity true;}).AddShardingTransaction((connection, builder) builder.UseSqlServer(connection)).AddDefaultDataSource(ds0, Server.;DatabaseTodoApp;Trusted_ConnectionTrue).AddShardingTableRoute(o {o.AddShardingTableRouteToDoItemVirtualTableRoute();}).End();public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
//4.初始化分表配置var shardingBootstrapper app.ApplicationServices.GetRequiredServiceIShardingBootstrapper();shardingBootstrapper.Start();综上所述我们接入任何efcore的系统只需要进行4步(第一步都可以去掉只需要3步)就可以完美接入了可以保证使用abp正式接入替换修改将todoitem表作为id取模来进行分表演示修改TodoItem实体默认TodoApp有一个TodoItem实体对象我们首先创建两个空接口//标识对应分表对像的i分表字段是id,是自动创建的guidpublic interface IShardingKeyIsGuId{}
//标识对应的分表对应的分表字段是创建时间public interface IShardingKeyIsCreationTime{}
//修改TodoItempublic class TodoItem : BasicAggregateRootGuid,IShardingTable,IShardingKeyIsGuId{[ShardingTableKey]public override Guid Id { get; protected set; }public string Text { get; set; }}创建TodoItem的分表路由通过继承默认分表取模路由AbstractSimpleShardingModKeyStringVirtualTableRoute//id取模虽然是string但是guid也是一样的最多两位就是00_99按5来取模public class ToDoItemVirtualTableRoute:AbstractSimpleShardingModKeyStringVirtualTableRouteTodoItem{public ToDoItemVirtualTableRoute() : base(2, 5){}}实现抽象类修改TodoItemDbContext实现 AbstractShardingAbpDbContextpublic class TodoAppDbContext :AbstractShardingAbpDbContextTodoAppDbContext,IIdentityDbContext,ITenantManagementDbContext,IShardingTableDbContext修改实体TodoItempublic class TodoItem : BasicAggregateRootGuid,IShardingTable,IShardingKeyIsGuId{[ShardingTableKey]public override Guid Id { get; protected set; }public string Text { get; set; }}其中别的接口都和sharding-core一致,为了支持abp的部分自动属性这边进行了新的接口添加用来标识当前的对象是通过什么方式来进行分表的,然后可以高效的通过接口来进行赋值比如IShardingKeyIsGuId告诉系统是id为guid的进行分表的public abstract class AbstractShardingAbpDbContextTDbContext...
{
......private void CheckAndSetShardingKeyThatSupportAutoCreateTEntity(TEntity entity) where TEntity : class{if (entity is IShardingKeyIsGuId){if (entity is IEntityGuid guidEntity){if (guidEntity.Id ! default){return;}var idProperty entity.GetProperty(nameof(IEntityGuid.Id));var dbGeneratedAttr ReflectionHelper.GetSingleAttributeOrDefaultDatabaseGeneratedAttribute(idProperty);if (dbGeneratedAttr ! null dbGeneratedAttr.DatabaseGeneratedOption ! DatabaseGeneratedOption.None){return;}EntityHelper.TrySetId(guidEntity,() GuidGenerator.Create(),true);}}else if (entity is IShardingKeyIsCreationTime){AuditPropertySetter?.SetCreationProperties(entity);}}
}添加虚拟路由既然你讲TodoItem进行了分表那么你这边需要告诉系统你是按怎么个规则进行分表的假设我们默认按id取模那么可以继承sharding-core默认提供的取模路由public class ToDoItemVirtualTableRoute:AbstractSimpleShardingModKeyStringVirtualTableRouteTodoItem{public ToDoItemVirtualTableRoute() : base(2, 5){}}简单说明就是分表后缀为2位数00-99,5代表模5也就是00,01,02,03,04注意 IShardingTableDbContext如果dbcontext需要实现分表功能必须实现IShardingTableDbContext到目前为止我们的准备工作已经完成了接下来需要进行codefirst的支持和具体项目的配置使用了选中TodoApp.EntityFrameworkCore项目打开TodoAppDbContextFactory替换dbcontext的创建方法主要是替换codefirst的建表语句这边是采用了EFCore.Shardingstatic TodoAppDbContextFactory(){var services new ServiceCollection();var configuration BuildConfiguration();services.AddShardingDbContextTodoAppDbContext((conn, o) o.UseSqlServer(conn).ReplaceServiceIMigrationsSqlGenerator, ShardingSqlServerMigrationsSqlGeneratorTodoAppDbContext()).Begin(o {o.AutoTrackEntity true;}).AddShardingTransaction((connection, builder) builder.UseSqlServer(connection)).AddDefaultDataSource(ds0,configuration.GetConnectionString(Default)).AddShardingTableRoute(o {o.AddShardingTableRouteToDoItemVirtualTableRoute();}).End();services.AddLogging();var buildServiceProvider services.BuildServiceProvider();ShardingContainer.SetServices(buildServiceProvider);new ShardingBootstrapper(buildServiceProvider).Start();}public TodoAppDbContext CreateDbContext(string[] args){return ShardingContainer.GetServiceTodoAppDbContext();}主要代码就是告诉efcore.tools如何创建对应的dbcontext然后打开nuget控制台选中需要生成迁移的项目启动项设置为执行命令PM Add-Migration InitTodoAppPM update-database到此为止我们的code first已经完成了,系统会自动根据分表的配置来进行创建对应的sql语句abp启动因为sharding-core是基于接口和dbcontext所以只要你的efcore那么基本上你的生态就可以接入sharding-core,主要就是注意1点自定义替换DbContextOptions的部分服务dbcontext的构造函数是DbContextOptions或者是他的泛型类修改TodoAppEntityFrameworkCoreModulepublic override void ConfigureServices(ServiceConfigurationContext context){......ConfigureAbpDbContextOptions(options {/* The main point to change your DBMS.* See also TodoAppDbContextFactory for EF Core tooling. */options.UseSqlServer();options.ConfigureTodoAppDbContext(context1 {context1.DbContextOptions.UseSqlServer(Server.;DatabaseTodoApp;Trusted_ConnectionTrue).UseShardingTodoAppDbContext();});});ShardingCoreHelper.CheckContextConstructorsTodoAppDbContext();new ShardingCoreConfigBuilderTodoAppDbContext(context.Services,((s, builder) {builder.UseSqlServer(s);} )).Begin(o {o.CreateShardingTableOnStart false;o.EnsureCreatedWithOutShardingTable false;o.AutoTrackEntity true;}).AddShardingTransaction((connection, builder) builder.UseSqlServer(connection)).AddDefaultDataSource(ds0, Server.;DatabaseTodoApp;Trusted_ConnectionTrue).AddShardingTableRoute(o {o.AddShardingTableRouteToDoItemVirtualTableRoute();}).End();}public override void OnPostApplicationInitialization(ApplicationInitializationContext context){context.ServiceProvider.GetRequiredServiceIShardingBootstrapper().Start();}稍微解释下options.ConfigureTodoAppDbContext(context1 {context1.DbContextOptions.UseSqlServer(Server.;DatabaseTodoApp;Trusted_ConnectionTrue).UseShardingTodoAppDbContext();});用来告诉abpTodoAppDbContext的创建需要使用useSharding之后就是sharding-core默认提供的builder,当然你们可以自行封装一下别忘了在启动的时候context.ServiceProvider.GetRequiredServiceIShardingBootstrapper().Start();这个千万不能忘运行TodoApp.Web通过添加efcore的日志我们可以清晰地看到abp能够正确的将对应的数据插入进去,并且完全不需要修改现有代码,基本上的零基础使用,简单的配置,如果您喜欢本库就点点star点点赞来都来了点个推荐不过分吧。为.net生态做一份贡献,希望各位个多多提issue和pr十分感激项目demoAbpVNextShardingTodoApp