更多精彩推荐,上午11点到达

在平时的开发中,受到传统模式的影响,我们都是习惯了单一的数据库表操作,把数据都建到一个库里边,然后进行增删改查,这个是很经典的开发模式。

但是随着项目开发,总会出现这样的应用场景:
1、我们新的系统建立了新库,但是老板让我们把具有相同结构的老数据库也带上(导入到一起或者定时同步,这里不讨论)

2、项目慢慢变大,我们要分库分表了,可能订单数据和用户数据被分开了,但是同一个api业务逻辑里,可能我们需要操作多个DB,比如我正在走的是主库,然后有一个操作,需要把数据从另一个DB里区保存或者查询。

3、想在测试的时候,同时无缝测试多个库连接,比如我的Blog.Core,每次我提交一个版本,都需要对Sqlite、MySql、MSSql(LocalDB)等同时做测试,那我就想在不停掉项目的前提下,做多库测试。

其实说了那么多,就是想实现一个工作,就是多库操作,毕竟这是一个趋势,今天我们就简单说一下多库操作的第一弹 —— 动态切换数据库。过程很简单,这里就先说一下吧。

鸣谢:@Game结束 小伙伴提供思路和代码。

1、修改配置DB连接字符串集合

目前我的Blog.Core项目中,使用的是SqlSugar的ORM,如果你用其他的,也是可以的,思路都是一样的,可能具体操作细节和写法上不太一样。

修改我们的appsettings.json,配置连接字符串

  "DBS": [/*MySql = 0,SqlServer = 1,Sqlite = 2,Oracle = 3,PostgreSQL = 4*/{"ConnId": 1,// 连接id,可以配置到数据库"DBType": 2,// db类型,枚举,具体的看上边"Enabled": true,// 是否开启当前数据库db"Connection": "WMBlog.db" // 连接字符串},{"ConnId": 2,"DBType": 1,"Enabled": true,"Connection": "Server=.;Database=WMBlogDB;User ID=sa;Password=123;","ProviderName": "System.Data.SqlClient"},{"ConnId": 3,"DBType": 0,"Enabled": false,"Connection": "Server=localhost; Port=3306;Stmt=; Database=wmblogdb; Uid=root; Pwd=456;"},{"ConnId": 4,"DBType": 3,"Enabled": false,"Connection": "Provider=OraOLEDB.Oracle; Data Source=WMBlogDB; User Id=sss; Password=789;","OracleConnection_other1": "User ID=sss;Password=789;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.8.65)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME = orcl)))"}],

这个设计很简单,我们可以配置到appsettings.json里,同时也可以配置到内存里,至于能不能放到数据库里,我还没有操作过,不过放到配置文件里已经基本可以了。

2、配置连接数据对象

我们这里使用的既然是Sqlsugar,那就把相应的连接配置对象注入到服务里,本来使用的是上下文,但是后来为了事务,也发现上下文有点儿多余,因为sqlsugar自带了部分上下文的功能,所以就直接使用的ISqlSugarClient。

那首先我们就需要把刚刚json配置文件的连接字符串,封装一下:

在 Common 层的 BaseDBConfig 中,创建操作类:

 public class MutiDBOperate{public string ConnId { get; set; }public string Conn { get; set; }public DataBaseType DbType { get; set; }}

然后把json数据封装一下:

 public static List<MutiDBOperate> MutiConnectionString => MutiInitConn();public static List<MutiDBOperate> MutiInitConn(){List<MutiDBOperate> listdatabase = new List<MutiDBOperate>();string Path = "appsettings.json";using (var file = new StreamReader(Path))using (var reader = new JsonTextReader(file)){var jObj = (JObject)JToken.ReadFrom(reader);if (!string.IsNullOrWhiteSpace("DBS")){var secJt = jObj["DBS"];if (secJt != null){for (int i = 0; i < secJt.Count(); i++){if (secJt[i]["Enabled"].ObjToBool()){listdatabase.Add(SpecialDbString(new MutiDBOperate(){ConnId = secJt[i]["ConnId"].ObjToString(),Conn = secJt[i]["Connection"].ObjToString(),DbType = (DataBaseType)(secJt[i]["DBType"].ObjToInt()),}));}}}}return listdatabase;}}

3、注入服务

这里要说一下,既然是多个库连接,我就需要一个主库,就是当前的DB,为了达到切换的目的,我也在配置文件里做了相应的配置:

这个值,就是当前某一个连接对象的ConnId。同时也为了在代码里能控制这个值,我采用对象静态类的方式:

namespace Blog.Core.Common.DB
{public static class MainDb{// 这个id,就是我们配置文件的idpublic static string CurrentDbConnId = "1";}
}

现在我们把刚刚的配置数据对象一起注入到服务里:

 /// <summary>/// SqlSugar 启动服务/// </summary>public static class SqlsugarSetup{public static void AddSqlsugarSetup(this IServiceCollection services){if (services == null) throw new ArgumentNullException(nameof(services));// 把多个连接对象注入服务,这里可以采用Transient瞬态,也可以Scopeservices.AddTransient(o =>{List<ISqlSugarClient> sqlSugarClients = new List<ISqlSugarClient>();var beforeDbConnect = BaseDBConfig.MutiConnectionString;var index = beforeDbConnect.FindIndex(x => x.ConnId == MainDb.CurrentDbConnId);if (index > 0){// 做一个交换,切换主db连接放到第一位var firstDb = beforeDbConnect[0];var changeDb = beforeDbConnect[index];beforeDbConnect[index] = firstDb;beforeDbConnect[0] = changeDb;}beforeDbConnect.ForEach(m =>{sqlSugarClients.Add(new SqlSugarClient(new ConnectionConfig(){ConfigId = m.ConnId,ConnectionString = m.Conn,DbType = (DbType)m.DbType,IsAutoCloseConnection = true,//InitKeyType = InitKeyType.SystemTable}));});return sqlSugarClients;});}}

4、仓储构造函数注入DB

目前我采用的架构是【service+repository+unitofwork】的模式,所以我们获取的Db就是ISqlSugarClient实例,那我们就把它注入进去。

在 UnitOfWork 的构造函数中,注入:

 private readonly List<ISqlSugarClient> _sqlSugarClients;public UnitOfWork(List<ISqlSugarClient> sqlSugarClients){// 每次取最上边的db,这个顺序已经在注册服务的时候,切换好了_sqlSugarClient = sqlSugarClients[0];  }

5、其他修改

我们修改了db连接方式,那项目启动时候Seed种子数据的上下文也需要更改一下:

6、做下测试,动态切换

那到底能不能使用呢,这里我们测试一下:

首先我们打开两个数据库连接,一个是Sqlite,一个是MSSql,同时我们在两个各自的博客表中,数据做区分。

我们先执行一下blog查询,然后把maindb切换成"2"频道,也就是mssql的:

并不完美,遗留问题

这样我们每次访问api,是可以单独的做控制,但是这里有一个问题,就是我们同一个api内,是无法实现动态切换的目的的,我也在研究,在下篇文章中,我会想办法解决这个问题。

多库操作:多个数据库的动态切换(一)相关推荐

  1. Spring学习总结(16)——Spring AOP实现执行数据库操作前根据业务来动态切换数据源

    深刻讨论为什么要读写分离? 为了服务器承载更多的用户?提升了网站的响应速度?分摊数据库服务器的压力?就是为了双机热备又不想浪费备份服务器?上面这些回答,我认为都不是错误的,但也都不是完全正确的.「读写 ...

  2. springboot+redis切换指定数据库or动态切换数据库

    redis切换数据库 项目使用指定的数据库 项目中动态切换数据库 项目使用指定的数据库 需求1: 甲方有很多系统用redis,我们这个系统需要指定用到4数据库 在配置文件中设置数据库 spring:r ...

  3. 【MySQL】表操作和库操作

    文章目录 概念 库操作 1.创建数据库 2.删除数据库 3.选择数据库 4.显示数据库列表 表操作 1.创建数据表CREATE 2.删除数据表DROP 3.插入数据INSERT 4.更新数据UPDAT ...

  4. Spring 配置多个数据源,并实现动态切换

    1.配置两个不同的数据源,如下 <!-- 数据源配置1 --> <bean id="testDataSource1" class="com.alibab ...

  5. .NET 使用 MySql.Data.dll 动态库操作MySql的帮助类--MySqlHelper

    .NET 使用 MySql.Data.dll 动态库操作MySql的帮助类--MySqlHelper 參考演示样例代码,例如以下所看到的: /// <summary>/// MySql 数 ...

  6. $cfg_dbtype = mysql_多库操作2:终于实现多个数据库操作

    publicUnitOfWork( ISqlSugarClient sqlSugarClient){_sqlSugarClient = sqlSugarClient;} //获取DB,保证唯一性//p ...

  7. C++ 使用Poco库操作SQLite数据库

    C++ 使用Poco库操作SQLite数据库 flyfish 文章目录 C++ 使用Poco库操作SQLite数据库 数据库插入记录 数据库插入记录方式2 数据库插入记录方式3 更方便的数据库插入记录 ...

  8. 第八章| 1. MySQL数据库|库操作|表操作

    1.初识数据库 我们在编写任何程序之前,都需要事先写好基于网络操作一台主机上文件的程序(socket服务端与客户端程序),于是有人将此类程序写成一个 专门的处理软件,这就是mysql等数据库管理软件的 ...

  9. 数据库面试 - 如何设计才可以让系统从未分库分表动态切换到分库分表上?

    数据库面试 - 如何设计才可以让系统从未分库分表动态切换到分库分表上? 面试题 现在有一个未分库分表的系统,未来要分库分表,如何设计才可以让系统从未分库分表动态切换到分库分表上? 面试官心理分析 你看 ...

最新文章

  1. 白平衡——图像处理中的一种增强技术
  2. 通过HttpListener实现简单的Http服务
  3. Log4j的FileAppender配置
  4. 好好珍惜今生,不要期待来世……
  5. 初学java小白的疑惑梳理
  6. xwpython aui 子窗口-Python/wxPython:AUI管理器,防止面板离开Fram
  7. 10行代码解析krc歌词文件
  8. 细数音频放大器的分类
  9. Spring MVC 起步
  10. 【转】curl 查看一个web站点的响应时间(rt)
  11. 六轴传感器使用学习记录
  12. Unity实时涂鸦绘画插件:RealTime Painting
  13. outlook登陆Exchange邮箱不断掉线并弹出需要登陆的窗口
  14. 僵尸网络新世界:摄像头的背叛和战争
  15. 抓取chrome所有版本密码
  16. 支付宝APP支付之查看支付宝商户ID
  17. 【前端开发基础】CSS基础知识以及CSS3
  18. DevOps功能实现解析
  19. 基于MessageSolution 邮件归档系统EEA的通用型信息泄露漏洞挖洞
  20. HTML清新卡通人物404单页源码分享

热门文章

  1. sdut2784cf 126b Good Luck!(next数组)
  2. Win7系统中必需记住的14个常用快捷键
  3. ListBox类似组件,鼠标右键点击事件得到选中Item
  4. 如何在iPhone上共享视频之前从视频中删除音频
  5. mysql索引三个字段查询两个字段_mysql中关于关联索引的问题——对a,b,c三个字段建立联合索引,那么查询时使用其中的2个作为查询条件,是否还会走索引?...
  6. .gitignore文件将已经纳入版本管理的文件删除
  7. 以当天日期时间,打包目录
  8. 微信小程序黑客马拉松即将开始,来做最酷的 Mini Program Creators!
  9. 关于质量的联想:消费示范效应
  10. 手游开发者交流会议暨OGEngine新版发布