介绍
本期主角:ShardingCore
一款ef-core下高性能、轻量级针对分表分库读写分离的解决方案,具有零依赖、零学习成本、零业务代码入侵
dotnet下唯一一款全自动分表,多字段分表框架,拥有高性能,零依赖、零学习成本、零业务代码入侵,并且支持读写分离动态分表分库,同一种路由可以完全自定义的新星组件,通过本框架你不但可以学到很多分片的思想和技巧,并且更能学到Expression
的奇思妙用
你的star和点赞是我坚持下去的最大动力,一起为.net生态提供更好的解决方案
项目地址
github地址 https://github.com/xuejmnet/sharding-core
gitee地址 https://gitee.com/dotnetchina/sharding-core
背景
直接开门见山,你有没有这种情况你需要将一批数据用时间分片来进行存储比如订单表,订单表的分片字段是订单的创建时间
,并且id是雪花id
,订单编号
是带时间信息的编号,因为.net下的所有分片方案几乎都是只支持单分片字段,所以当我们不使用分片字段查询也就是订单创建时间查询的话会带来全表查询,导致性能下降,譬如我想用雪花id
或者订单编号
进行查询,但是带来的却是内部低效的结果,针对这种情况是否有一个好的解决方案呢,有但是需要侵入业务代码,根据雪花id或者订单编号进行解析出对应的时间然后手动指定分片
前提是框架支持手动指定
.基于上述原因ShardingCore
带来了全新版本 x.3.2.x+ 支持多字段分片路由,并且拥有很完美的实现,废话不多说我们直接开始吧!!!!!!!!!!!
原理
我们现在假定一个很简单的场景,依然是订单时间按月分片,查询进行如下语句
//这边演示不使用雪花id因为雪花id很难在演示中展示所以使用订单编号进行演示格式:yyyyMMddHHmmss+new Random().Next(0,10000).ToString().PadLeft(4,'0')
var dateTime = new DateTime(2021, 11, 1);
var order = await _myDbContext.Set<Order>().Where(o => o.OrderNo== 202112201900001111&&o.CreateTime< dateTime).FirstOrDefaultAsync();
上述语句OrderNo会查询Order_202112这张表,然后时间索引会查询......Order_202108、Order_202109、Order_202110,然后两者取一个交集我们发现其实是没有结果的,这个时候应该是返回默认值null或者直接报错
这就是一个简单的原理
直接开始
接下来我将用订单编号和创建时间来为大演示,数据库采用sqlserver(你也可以换成任意efcore支持的数据库),其中编号格式yyyyMMddHHmmss+new Random().Next(0,10000).ToString().PadLeft(4,'0'),创建时间是DateTime格式并且创建时间按月分表,这边不采用雪花id是因为雪花id的实现会根据workid和centerid的不一样而出现不一样的效果,接下来我们通过简单的5步操作实现多字段分片
添加依赖
首先我们添加两个依赖,一个是ShardingCore
一个EFCore.SqlServer
//请安装最新版本目前x.3.2.x+,第一个版本号6代表efcore的版本号
Install-Package ShardingCore -Version 6.3.2
Install-Package Microsoft.EntityFrameworkCore.SqlServer -Version 6.0.1
创建一个订单对象
public class Order
{
public string Id { get; set; }
public string OrderNo { get; set; }
public string Name { get; set; }
public DateTime CreateTime { get; set; }
}
创建DbContext
这边就简单的创建了一个dbcontext,并且设置了一下order如何映射到数据库,当然你可以采用attribute的方式而不是一定要fluentapi
/// <summary>
/// 如果需要支持分表必须要实现<see cref="IShardingTableDbContext"/>
/// </summary>
public class DefaultDbContext:AbstractShardingDbContext,IShardingTableDbContext
{
public DefaultDbContext(DbContextOptions options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Order>(o =>
{