• EFCore动态切换Schema


    最近做个分库分表项目,用到schema的切换感觉还是有些坑的,在此分享下。

    先简要说下我们的分库分表

    分库分表规则

    我定的规则是,订单号(数字)除以16,得出的结果为这个订单所在的数据库,然后他的余数代表他所在这个库里面的哪个表。

    然后在一个库里面有16个表,这个怎么实现呢?比较龊的办法是 Order1/Order2这样,不过后来我想了下,数据库默认(我们是Sql Server)是有schema的(默认是dbo的那个东西),

    然后我就打起这个东西的主意,后续跟dba确认方案可行后,就决定比如在同一个库里,第一套订单表是 p0.Order,第二套订单表就是p1.Order(有效取值 p0~p15)。

    代码设计

    如果说每次操作订单,你都要记得要先根据订单号拆分规则,找到这是哪个数据库,再去找这是哪个schema,我觉得这代码也别写了,放弃把,这是不可维护的代码,不具备可持续发展性。

    我们必须要将一个分库分表这么一件事,抽象为某个单一的逻辑。

    于是乎,DbContext是个好东西!

    当我们在说Ef的时候,实际上我们在讨论的主要就是他里面的DbContext。而一个DbContext,则逻辑上代表了一个数据库映射(包含数据库连接/表等和数据库相关的所有配置的集合)。

    只要我们将分库分表这件事,抽象为如何获取一个DbContext,之后在对这个DbContext做你想做的操作,那么一切事情就简单多了!

    于是乎我设计了这么一个接口:

    image

    你给我一个订单号,我还你一个DbContext~

    正题

    如何让DbContext支持分库分表

    这里主要有2个问题,一个是如何改连接字符串,另一个如何改schema。

    问题1简单,创建DbContext的时候本来就是要串连接字符串进去的,直接这里构造好连接字符串即可。

    问题2比较复杂,也是这篇文章主要内容,首先我的设计是在创建DbContext,传入schema,在OnModelCreating里用这个schema初始化。

    代码是这样子的:

    image

    于是乎你第一次创建DbContext的时候,schema是什么(别在意我代码变量名当时写错了这么个细节),就永远是什么,后续你重复创建其他DbContext的时候其实这句话并不能让你修改schema。

    后面我发觉,EfCore在指定表名的时候,是可以顺带指定schema的,于是乎在改下,改成了类似这样:

    image

    然而实践证明依然并没有什么卵用。

    坑了2次后我严重怀疑efcore里一定有某种级别的缓存机制,使得初次赋值之后某些信息不会再被更新(甚至于怀疑到efcore2.x引入的DbContextPool,然而我都是new出来的我没pool啊)。

    后面一通乱找后不记得再哪个网址(但是记得一定是stackoverflow里)找到了对这个类 IModelCacheKeyFactory的一些描述。

    好像是efcore会对Model(你的实体)和DbContext之间产生一个缓存,而我的分库分表用的DbContext只有一个(只是动态修改了某些参数配置),于是乎觉得应该就是这个东西缓存了的关系导致,然后我重写了这货的实现:

    image

    本质就是将DbContext里的当前的Schema暴露出给ModelCacheKey读取,然后进行Equal比较的时候Schema也作为一个Equal的因素,当两者比较不等的时候,就不会再采用之前错误Schema的缓存了

    最后在创建DbContextOptionBuilder的时候Replace一下

    builder.ReplaceService<IModelCacheKeyFactory, SchemaModelCacheFactory>();

    即可完成

    后续亲测都能动态切换schema,圆满完成。

    后面发现(评论里提到的)其实这里已经有说明这个问题了,文档看不仔细,躺坑两行泪

    https://docs.microsoft.com/zh-cn/ef/core/modeling/dynamic-model

  • 相关阅读:
    List
    美团Leaf分布式ID生成策略
    单点登陆
    ElasticSearch
    Eureka
    Nginx
    UML
    Computer English
    加密
    Excel中把一列数据转换成逗号隔开的一行
  • 原文地址:https://www.cnblogs.com/leolaw/p/10461156.html
Copyright © 2020-2023  润新知