EFCore动态切换Schema

原文: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做你想做的操作,那么一切事情就简单多了!

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

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

正题

如何让DbContext支持分库分表

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

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

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

代码是这样子的:

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

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

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

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

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

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

本质就是将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

原文地址:https://www.cnblogs.com/lonelyxmas/p/10747712.html

时间: 2024-10-20 19:24:46

EFCore动态切换Schema的相关文章

Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法(转)

一.开篇 这里整合分别采用了Hibernate和MyBatis两大持久层框架,Hibernate主要完成增删改功能和一些单一的对象查询功能,MyBatis主要负责查询功能.所以在出来数据库方言的时候基本上没有什么问题,但唯一可能出现问题的就是在hibernate做添加操作生成主键策略的时候.因为我们都知道hibernate的数据库本地方言会针对不同的数据库采用不同的主键生成策略. 所以针对这一问题不得不采用自定义的主键生成策略,自己写一个主键生成器的表来维护主键生成方式或以及使用其他的方式来生成

基于spring+mybatis+atomikos+jta实现分布式事务(2)-动态切换数据源

本文介绍基于spring+mybatis+atomikos+jta实现分布式事务,由程序动态切换数据源,通过atomikos可实现分布式事务一致性. 版本:spring-3.2.9.RELEASE.mybatis-3.4.4.atomikos-4.0.5.jdk1.8 1,maven配置文件pom.xml如下: <!-- test --> <dependency> <groupId>junit</groupId> <artifactId>juni

spring动态切换数据源(一)

介绍下spring数据源连接的源码类:| 1 spring动态切换连接池需要类AbstractRoutingDataSource的源码 2 /* 3 * Copyright 2002-2017 the original author or authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in comp

Spring整合多数据源实现动态切换

在实际项目中时常需要连接多个数据库,而且不同的业务需求在实现过程当中往往需要访问不同的数据库. jdbc.properties配置文件,配置多个dataSource ##########################MySQL##################################### hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect connection.driver_class=com.mysql.jdbc.

实现flex LinkBar 组件 动态切换ico图标

<?xml version="1.0" encoding="utf-8"?><s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"                        xmlns:s="library://ns.adobe.com/flex/spark"                        xmlns:mx="

mybatis动态切换数据源

(#)背景:由于业务的需求,导致需要随时切换15个数据源,此时不能low逼的去写十几个mapper,所以想到了实现一个数据源的动态切换 首先要想重写多数据源,那么你应该理解数据源的一个概念是什么,DataSourceTransactionManager这个类就是spring中对于数据源的封装,其中DataSource做为 他的一个成员.接下来我们要介绍一下我们切换动态数据源需要使用的类,AbstractRoutingDataSource,先来看看这个类的源码 首先看看这几个变量,targetDa

django 板块动态切换

需求:在同一页面的不同板块上可以实现动态切换,使用一个view实现,具体如下图所示,点击phy显示物理机列表,点击vm显示虚机列表,phy.vm对应的url均是动态生成:               实现思路: 1.新建两个表,servers表用于存放服务器种类,pvserver物理机虚机具体服务器信息.物理机和虚机不要分别存放于两个表中,这样的话在view中无法直接通过服务器类型得出相应的服务器列表 #存放服务器类型 class servers(models.Model): serverid

动态切换tableView中的cell的种类

为什么要动态切换tableView中cell的种类呢?如果项目经理不出这种需求,你也就见不到这篇文章了:) 效果: 源码: 首先,你要准备3种cell,直接继承系统的就行了. // // RootViewController.m // ChangeCell // // Copyright (c) 2014年 Y.X. All rights reserved. // #import "RootViewController.h" #import "YellowCell.h&quo

基于Struts2 Spring ibatis Oracle10g架构 多数据源动态切换实例

一.概述 基于Spring动态配置多数据源,在大型的应用中对数据进行切分,并且采用多个数据库实例进行管理,这样可以有效的提高系统的水平伸缩性,而这样的解决方案就会补同于常见的单一数据实例的方案,这就要程序在运行时根据当时的请求以及系统状态来动态的决定将数据存储在哪个数据库实例中,以及从哪个数据库提取数据. Spring配置多个数据源的方式和具体使用过程,Spring对于多数据源,以数据库表为参照,大体上可以分为两大类情况: 1.表级上的跨数据库,即对于不同的数据库却有不相同的表(表名和表结构完全