.net core 使用 ShardingCore 按时间分表(一)

ShardingCore 官方文档地址

快速上手AspNetCore | ShardingCore文档 (xuejmnet.github.io)

Nuget 下载

ShardingCore

注意 ShardingCore 包中含有 Microsoft.EntityFrameworkCore 包 Microsoft.EntityFrameworkCore.Relational 包

 所以 项目 就没有必要在 单独引用 Microsoft.EntityFrameworkCore 包

ShardingCore 抽象 封装了 DBContext  抽象类为 AbstractShardingDbContext 所以 只需要继承该抽象类即可

 

 分表操作 主要实现 IShardingTableDbContext 接口

 

虚拟路由 按时间分

AbstractSimpleShardingMonthKeyDateTimeVirtualTableRoute

 

 

 

 

上代码

搞个简单类

public class Order
    {
        [Key]
        public string Id { get; set; }
        public string Payer { get; set; }
        public long Money { get; set; }
        public string Area { get; set; }
        public OrderStatusEnum OrderStatus { get; set; }

        public string UserId { get; set; }

        public DateTime CreationTime { get; set; }
    }
    public enum OrderStatusEnum
    {
        NoPay = 1,
        Paying = 2,
        Payed = 3,
        PayFail = 4
    }

 

public class MyDbContext : AbstractShardingDbContext, IShardingTableDbContext
    {
        public MyDbContext(DbContextOptions options) : base(options)
        {           
        }
        public DbSet<Order> Orders { get; set; }
        public IRouteTail RouteTail { get; set; }
    }

 

按时间分表

public class OrderVirtualTableRoute : AbstractSimpleShardingMonthKeyDateTimeVirtualTableRoute<Order>
    {
        public override DateTime GetBeginTime()
        {
            return new DateTime(2023, 5, 1);
        }
        //注意一定要配置或者采用接口+标签也是可以的
        public override void Configure(EntityMetadataTableBuilder<Order> builder)
        {
            builder.ShardingProperty(o => o.CreationTime);
        }

        public override bool AutoCreateTableByTime()
        {
            return true;
        }
    }

数据迁移需要实现 MySqlMigrationsSqlGenerator

 public class ShardingMySqlMigrationsSqlGenerator : MySqlMigrationsSqlGenerator
    {
        private readonly IShardingRuntimeContext _shardingRuntimeContext;
        public ShardingMySqlMigrationsSqlGenerator(IShardingRuntimeContext shardingRuntimeContext, MigrationsSqlGeneratorDependencies dependencies, ICommandBatchPreparer commandBatchPreparer, IMySqlOptions options) : base(dependencies, commandBatchPreparer, options)
        {
            _shardingRuntimeContext = shardingRuntimeContext;
        }
        protected override void Generate(
            MigrationOperation operation,
            IModel model,
            MigrationCommandListBuilder builder)
        {
            var oldCmds = builder.GetCommandList().ToList();
            base.Generate(operation, model, builder);
            var newCmds = builder.GetCommandList().ToList();
            var addCmds = newCmds.Where(x => !oldCmds.Contains(x)).ToList();
            MigrationHelper.Generate(_shardingRuntimeContext, operation, builder, Dependencies.SqlGenerationHelper, addCmds);
        }
    }

种子数据

 //种子数据
    public static class StartupExtension
    {
        //public static void UseShardingCore(this IApplicationBuilder app)
        //{
        //    app.ApplicationServices.GetRequiredService<IShardingBootstrapper>().Start();
        //}
        public static void InitSeed(this IApplicationBuilder app)
        {
            using (var serviceScope = app.ApplicationServices.CreateScope())
            {
                var myDbContext = serviceScope.ServiceProvider.GetRequiredService<MyDbContext>();
                if (!myDbContext.Set<Order>().Any())
                {
                    List<Order> orders = new List<Order>(10);
                    var begin = new DateTime(2023, 5, 1, 3, 3, 3);
                    for (int i = 0; i < 10; i++)
                    {
                        var order = new Order()
                        {
                            Id = i.ToString(),
                            Payer = $"{i % 10}",
                            Area ="A",
                            UserId ="11",
                            Money = 100 + new Random().Next(100, 3000),
                            OrderStatus = (OrderStatusEnum)(i % 4 + 1),
                            CreationTime = begin.AddDays(i)
                        };
                        orders.Add(order);
                    }
                    myDbContext.AddRange(orders);
                    myDbContext.SaveChanges();
                }
            }
        }
    }

 

依赖注入配置

builder.Services.AddShardingDbContext<MyDbContext>().UseRouteConfig(op =>
{
    //添加order表虚拟路由
    op.AddShardingTableRoute<OrderVirtualTableRoute>();
}).UseConfig(op =>
{
    ILoggerFactory factory = LoggerFactory.Create(config =>
        {
            config.AddConsole();
        });
    op.UseShardingMigrationConfigure(b =>
    {
        //数据迁移
        b.ReplaceService<IMigrationsSqlGenerator, ShardingMySqlMigrationsSqlGenerator>();
    });
    op.ThrowIfQueryRouteNotMatch = false;
    op.UseShardingQuery((conStr, builder) =>
    {
        //查询
        builder.UseMySql(conStr, MySqlServerVersion.AutoDetect(conStr)).UseLoggerFactory(factory);
    });
    op.UseShardingTransaction((connection, builder) =>
    {
        //事务
        builder.UseMySql(connection, MySqlServerVersion.AutoDetect(connection.ConnectionString)).UseLoggerFactory(factory);
    });
    //默认数据源
    op.AddDefaultDataSource("ds0", "Data Source=192.168.0.192;Initial Catalog=test;uid=root;pwd=123456;");
    op.AddReadWriteSeparation(sp =>
    {
        return new Dictionary<string, IEnumerable<string>>()
                        {
                        {
                            "ds0", new List<string>()
                            {
                                "Data Source=192.168.0.192;Initial Catalog=test;uid=root;pwd=123456;"
                            }
                        }
                        };
    }, ReadStrategyEnum.Loop, defaultEnable: true);
}).AddShardingCore();

 

中间件配置

//建议补偿表在迁移后面
using (var scope = app.Services.CreateScope())
{
    var myDbContext = scope.ServiceProvider.GetService<MyDbContext>();
    //如果没有迁移那么就直接创建表和库
    //myDbContext.Database.EnsureCreated();
    //如果有迁移使用下面的
     myDbContext.Database.Migrate();
}

//not required, enable check table missing and auto create,非必须  启动检查缺少的表并且创建
app.Services.UseAutoTryCompensateTable();

//种子数据
app.InitSeed();

 

 

posted on 2023-06-25 09:40  是水饺不是水饺  阅读(187)  评论(0编辑  收藏  举报

导航