实现原理

当我们new一个上下文DbContext 后, 每次执行CURD方式时 ,都会依次调用OnConfiguring(),OnModelCreating()两个方法。

  • OnConfiguring() 我们将用来替换一些服务实现,以支持分表的工作
  • OnModelCreating() 我们将用来重新实现 实体与数据库表 的映射关系

每次调用OnModelCreating()时,会判断实体与数据库表的映射关系有没有改变,如果改变则采用新的映射关系。

判断是否发生改变,通过替换 IModelCacheKeyFactory 接口的实现来完成。详情可见:在具有相同 DbContext 类型的多个模型之间进行交替

IModelCacheKeyFactory 实现

DbContextBase 是一个DbContext的实现,,ShardingRuleDbContextBase的一个共有属性。

根据分表规则的不同,每次的映射关系也会不同。

 public class DynamicModelCacheKeyFactoryDesignTimeSupport : IModelCacheKeyFactory
{
public object Create(DbContext context, bool designTime)
=> context is DbContextBase dynamicContext
? (context.GetType(), dynamicContext.ShardingRule, designTime)
: (object)context.GetType(); public object Create(DbContext context)
=> Create(context, false); }

OnConfiguring() 替换接口实现

 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
//如果分页规则有 ,代表需要分页, 那么需要替换对应的服务实现
if (!string.IsNullOrEmpty(this.ShardingRule))
{
optionsBuilder.ReplaceService<IModelCacheKeyFactory, DynamicModelCacheKeyFactoryDesignTimeSupport>();
}
}

ModelCustomizer 实现

在每次调用 OnModelCreating() 时,方法内部会调用实现IModelCustomizerModelCustomizer.csCustomize()方法,我们可以将映射关系写在此方法内。

通过继承实现:

IShardingTypeFinder 是一个类型查找器,请自行实现。

public class ShardingModelCustomizer : ModelCustomizer
{ public ShardingModelCustomizer(ModelCustomizerDependencies dependencies) : base(dependencies)
{
} public override void Customize(ModelBuilder modelBuilder, DbContext context)
{
base.Customize(modelBuilder, context);
var dbContextBase = context as DbContextBase;
var shardingTypeFinder = dbContextBase.ServiceProvider.GetService<IShardingTypeFinder>();
//查找需要重新映射表名的类
var shardingTypes = shardingTypeFinder.FindAll(true); if (shardingTypes != null && shardingTypes.Count() > 0)
{ if (context is DbContextBase contextBase)
{
if (!string.IsNullOrEmpty(contextBase.ShardingRule))
{
foreach (var type in shardingTypes)
{
switch (contextBase.DbContextOptions.DatabaseType)
{
case DatabaseType.SqlServer:
modelBuilder.Entity(type).ToTable($"{type.Name}_{contextBase.ShardingRule}");
break;
case DatabaseType.Sqlite:
modelBuilder.Entity(type).ToTable($"{type.Name}_{contextBase.ShardingRule}");
break;
case DatabaseType.MySql:
modelBuilder.Entity(type).ToTable($"{type.Name}_{contextBase.ShardingRule}".ToMySQLName());
break;
case DatabaseType.Oracle:
modelBuilder.Entity(type).ToTable($"{type.Name}_{contextBase.ShardingRule}".ToOracleName());
break;
default:
modelBuilder.Entity(type).ToTable($"{type.Name}_{contextBase.ShardingRule}");
break;
}
}
}
} } } }

OnConfiguring() 替换接口实现

  protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
//如果分页规则有 ,代表需要分页, 那么需要替换对应的服务实现
if (!string.IsNullOrEmpty(this.ShardingRule))
{
optionsBuilder.ReplaceService<IModelCacheKeyFactory, DynamicModelCacheKeyFactoryDesignTimeSupport>().ReplaceService<IModelCustomizer, ShardingModelCustomizer>();
}
}

DbContextBase构造函数修改

上文提到了ShardingRule 这个属性的出现 , 如何给这个属性赋值呢?

有两种方式:

  • 构造函数传参
  • 通过接口获取

构造函数传参

 public string ShardingRule { get; set; }
public DbContextBase(string shardingRule, DbContextOptions options) : base(options)
{
ShardingRule = shardingRule;
}

通过接口获取

IShardingRule是实现规则名称的自定义接口,自行实现

 protected DbContextBase(DbContextOptions options, IServiceProvider serviceProvider)
: base(options)
{
ShardingRule = (serviceProvider.GetService<IShardingRule>()).GetValue();
}

使用方式

这里只介绍构造函数传参使用方式

 DbContextOptionsBuilder<DbContextBase> optionsBuilder = new DbContextOptionsBuilder<DbContextBase>();
optionsBuilder.UseSqlServer("connStr");
var options = optionsBuilder.Options;
using (var dbContext = new DbContextBase("202209", options))
{
//TODO.... }

跨上下文使用事务

这里需要主要的是,跨上下文使用事务必须使用同一个连接,所以optionsBuilder.UseSqlServer(connection);这里的写法改变一下,使用同一连接

            DbContextOptionsBuilder<DbContextBase> optionsBuilder = new DbContextOptionsBuilder<DbContextBase>();
IDbConnection connection = new SqlConnection("connStr");
optionsBuilder.UseSqlServer(connection);
var options = optionsBuilder.Options;
using (var dbContext = new DbContextBase("202209", options))
{
using (var transaction =await dbContext.Database.BeginTransactionAsync())
{
using (var dbContext2 = new DbContextBase("202210", options))
{ await dbContext2.Database.UseTransactionAsync(transaction);
//TODO....
transaction.Commit();
}
} }

总结

EFCore分表的实现大致全是这样,没有什么区别。可以参考一些开源的框架,对现有的系统进行适当的调整,毕竟别人写的并不一定适合你。希望这篇文章可以帮到你。

EFCore分表实现的更多相关文章

  1. .Net下极限生产力之efcore分表分库全自动化迁移CodeFirst

    .Net下极限生产力之分表分库全自动化Migrations Code-First ## 介绍 本文ShardinfCore版本x.6.x.x+ 本期主角: - [`ShardingCore`](htt ...

  2. efcore分表下"完美"实现

    ShardingCore 如何呈现"完美"分表 这篇文章是我针对efcore的分表的简单介绍,如果您有以下需求那么可以自己选择是否使用本框架,本框架将一直持续更新下去,并且免费开源 ...

  3. efcore分表分库原理解析

    ShardingCore ShardingCore 易用.简单.高性能.普适性,是一款扩展针对efcore生态下的分表分库的扩展解决方案,支持efcore2+的所有版本,支持efcore2+的所有数据 ...

  4. EFCore.Sharding(EFCore开源分表框架)

    EFCore.Sharding(EFCore开源分表框架) 简介 引言 开始 准备 配置 使用 按时间自动分表 性能测试 其它简单操作(非Sharing) 总结 简介 本框架旨在为EF Core提供S ...

  5. 基于efcore的分表组件开源

    ShardingCore ShardingCore 是一个支持efcore 2.x 3.x 5.x的一个对于数据库分表的一个简易扩展, 目前该库暂未支持分库(未来会支持),仅支持分表,该项目的理念是让 ...

  6. EasySharding.EFCore 如何设计使用一套代码完成的EFCore Migration 构建Saas系统多租户不同业务需求且满足租户自定义分库分表、数据迁移能力?

    下面用一篇文章来完成这些事情 多租户系统的设计单纯的来说业务,一套Saas多租户的系统,面临很多业务复杂性,不同的租户存在不同的业务需求,大部分相同的表结构,那么如何使用EFCore来完成这样的设计呢 ...

  7. efcore使用ShardingCore实现分表分库下的多租户

    efcore使用ShardingCore实现分表分库下的多租户 介绍 本期主角:ShardingCore 一款ef-core下高性能.轻量级针对分表分库读写分离的解决方案,具有零依赖.零学习成本.零业 ...

  8. efcore在Saas系统下多租户零脚本分表分库读写分离解决方案

    efcore在Saas系统下多租户零脚本分表分库读写分离解决方案 ## 介绍 本文ShardinfCore版本x.6.0.20+ 本期主角: - [`ShardingCore`](https://gi ...

  9. EF多租户实例:快速实现分库分表

    前言 来到这篇随笔,我们继续演示如何实现EF多租户. 今天主要是演示多租户下的变形,为下图所示 实施 项目结构 这次我们的示例项目进行了精简,仅有一个API项目,直接包含所有代码. 其中Control ...

随机推荐

  1. &&与||的优先级比较

    &&与||的优先级比较类似于一种思维体操,更多的是造成矛盾,使得两者因为先后顺序的不同而造成的不同结果,当然有时候需要注意c语言中的短路运算. 方法1. 代码如下: 点击查看代码 #i ...

  2. WSL2安装Ubuntu20.04

    前言:听说WSL2需要Window版本在1904以上(我的window版本是1909,所以未能验证真实性) 启用WSL 控制面板 → 程序 → 程序和功能 → 启用或关闭Windows功能 勾选 适用 ...

  3. 非root源码安装gcc和cmake

    一.安装cmake 1.下载cmale 下载地址:https://cmake.org/files tar -zxvf cmake-3.19.8.tar.gz cd cmake-3.19.8/ ./co ...

  4. qbxt五一数学Day2

    目录 1. 判断素数(素性测试) 1. \(O(\sqrt n)\) 试除 2. Miller-Rabin 素性测试 * 欧拉函数 2. 逆元 3. exgcd(扩展欧几里得) 4. 离散对数(BSG ...

  5. Selenium自动化测试之Selenium IDE

    简介 Selenium IDE 是实现Web自动化的一种便捷工具,本质上它是一种浏览器插件.该插件支持Chrome和Firefox浏览器,拥有录制.编写及回放操作等功能,能够快速实现Web的自动化测试 ...

  6. PHP,javascript实现大文件上传

    HTML代码 <!doctype html> <html lang="en"> <head> <meta charset="UT ...

  7. Mac os:将Homebrew的下载源换成国内镜像增加下载速度(阿里云镜像)

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_135 可能所有的mac os系统爱好者都遇到过下面这种倒霉情况,在网络环境不太好的时候,你满怀期待的敲下 brew install ...

  8. Postman如何通过xmysql工具的Restful API 接口访问MySQL

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 导语 有时候用 Postman 接口测试需要获取MySQL的查询结果做接口输出的校验,这里介绍下 Postman 通过 R ...

  9. Apache DolphinScheduler 使用文档(4/8):软件部署

    本文章经授权转载,原文链接: https://blog.csdn.net/MiaoSO/article/details/104770720 目录 4. 软件部署 4.1 为 dolphinschedu ...

  10. Luogu2858[USACO06FEB]奶牛零食Treats for the Cows (区间DP)

    我是个傻逼,这么水的题都会T #include <iostream> #include <cstdio> #include <cstring> #include & ...