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

更多精彩推荐,上午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内,是无法实现动态切换的目的的,我也在研究,在下篇文章中,我会想办法解决这个问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/312649.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

超燃| 2019 中国.NET 开发者峰会视频发布

首届 .NET Conf China 2019 年&#xff0c;注定会是 .NET Core 社区发展的关键一年&#xff0c;诸多重大事件在这一年发生&#xff01;正如大家所期待的那样&#xff0c;刷新中国 .NET 社区的年度盛会——2019 中国 .NET 开发者峰会&#xff08;.NET Conf China 2019&#xff0…

Lingo优化模型概述

注意事项 lingo中变量默认是非负的示例 model: max 2*x1 3*x2; 2*x1 x2 < 8; 4*x1 3*x2 < 15; end数组型变量 集合段、数据段、目标与约束段、计算段、初始段和子模型段 model: sets: s/1..10/:x; endsetsdata: x 1 2 3 4 5 6 7 8 9 10; enddatamin sum(s(i):x…

刷新.NET

.NET Core 发布的那一天起&#xff0c;它在完成自我刷新的过程&#xff0c;一切为了适应未来&#xff0c;云原生。不仅仅跨平台那么简单。.NET Core 未来发展路线我们发现跳过了.NET Core 4.X 避免了和目前.NET Framework4.X命名上的混乱&#xff0c;明年直接命名为了.NET 5 &a…

如何备份和还原您的Kubernetes集群资源和持久卷?

众所周知&#xff0c;Kubernetes可以协调连接在一起&#xff0c;作为一个工作单元&#xff0c;形成高可用性的计算机集群。Kubernetes包含许多抽象概念&#xff0c;这些抽象概念允许将容器化的应用程序部署到集群中&#xff0c;而无需将它们附加到单独的机器上。简而言之&#…

sklearn评价指标

机器学习中&#xff0c;常见的评价指标如下&#xff1a; 准确率&#xff08;Accuracy&#xff09; 精确率&#xff08;Precision&#xff09; 灵敏度&#xff08;Sensitivity&#xff09;&#xff0c;即召回率&#xff08;Recall&#xff09; 特异度&#xff08;Specificity&am…

C# WPF抽屉效果实现

时间如流水&#xff0c;只能流去不流回&#xff01;点赞再看&#xff0c;养成习惯&#xff0c;这是您给我创作的动力&#xff01;本文 Dotnet9 https://dotnet9.com 已收录&#xff0c;站长乐于分享dotnet相关技术&#xff0c;比如Winform、WPF、ASP.NET Core等&#xff0c;亦有…

视频来了!Visual Studio Online 东半球首秀 @ .NET Conf 2019 中国峰会

2019 年 11 月 9 日&#xff0c; .NET Conf 2019 中国峰会于上海中谷小南国花园酒店举行&#xff0c;全国的 .NET 大咖相聚上海。这次我演讲的主题是《Visual Studio Code —— .NET 开发利器》。除了聊了聊韩老师开发的 .NET Core Test Explorer&#xff0c;还重点聊了聊 Visu…

开源性能监控工具APM之Skywalking和Pinpoint的实测对比

作者&#xff1a;zollty&#xff0c;资深程序员和架构师&#xff0c;私底下是个爱折腾的技术极客&#xff0c;架构师社区合伙人&#xff01;零&#xff0c;什么是APM&#xff1f;APM&#xff08;ApplicationPerformance Management&#xff09;是一种应用性能监控工具&#xff…

.Net Core 3.1,这匹黑马,2020年值得所有程序员重视!

强人掌舵 重回巅峰2014年萨蒂亚纳德拉接棒史蒂芬鲍尔默成为微软掌门人&#xff0c;五年的时间&#xff0c;纳德拉将夕阳西下、停滞不前的微软重新带回巅峰状态。2019年&#xff0c;微软今年挤下苹果&#xff0c;成为2019年全球市值最高企业&#xff0c;终止苹果过去7年来的龙头…

为什么你没有选择xamarin?

点击上方“dotNET全栈开发”&#xff0c;“设为星标”加“星标★”&#xff0c;每天11.50&#xff0c;好文必达全文约900字&#xff0c;预计阅读时间11分钟注&#xff1a;本篇文章只是关于xamarin的一个分享&#xff0c;没有xamarin技术深入的地方2019 年&#xff0c;注定会是 …

新款 Azure .NET SDK 如何设定 Content-Type

点击上方蓝字关注“汪宇杰博客”导语前不久我写了一篇《尝鲜新版 Azure .NET SDK》之后&#xff0c;使用了一段时间发现没爆&#xff0c;于是今天决定把博客的图片存储从旧版 SDK 迁移到新版 SDK&#xff0c;结果小收福报。Content-Type上传到 Azure Blob 的文件必须设置正确的…

聊聊程序员的成长与价值提升

一、 回顾我的职场体会我的职场生涯开始于十年前&#xff0c;一直在中小企业发展&#xff0c;未曾有幸到沿海那些高速发展的互联网公司工作&#xff0c;也就错过了互联网的大时代。但这不影响我的正常工作生活&#xff0c;事实上无论你身在何处&#xff0c;或在哪家公司&#x…

本地Jupyter连接远程linux服务器

连接的前提是本地装好了Jupyter&#xff0c;以及远程的服务器也配置好了。 先连接远程的Linux服务器&#xff0c;输入脚本命令&#xff1a; jupyter notebook得到执行结果&#xff1a; [I 14:29:11.290 NotebookApp] Serving notebooks from local directory: /home/ubuntu …

PowerBI 2019.12更新完美收官2019

PowerBI 的2019年12月更新来了。终于 PowerBI 完成了在 2019 年的进化。对于 12 月来说&#xff0c;最大的更新就是提供了主题设置&#xff0c;这使得我们彻底摆脱编写一个从来都不应该编写的JSON来设置主题文件。下面我们分别来详细介绍。自定义主题首先你需要打开预览&#x…

Task.CompletedTask和Task.Result小记

在任何返回Task的方法中&#xff0c;如果可以在不进行异步的情况下计算结果&#xff0c;则最好避免使用Task.Run。例如&#xff0c;一个简短的计算函数&#xff0c;或者测试中返回了一个预先计算过的结果&#xff0c;则无需使用Task.Run。例如&#xff0c;定义了一个返回Task的…

Dapr 运用之集成 Asp.Net Core Grpc 调用篇

前置条件&#xff1a; 《Dapr 运用》改造 ProductService 以提供 gRPC 服务从 NuGet 或程序包管理控制台安装 gRPC 服务必须的包Grpc.AspNetCore配置 Http/2gRPC 服务需要 Http/2 协议public static IHostBuilder CreateHostBuilder(string[] args) {return Host.CreateDefault…

蓝桥杯 印章拿金币

今日心得 对于大数组的定义要放在main函数外&#xff0c;否则会报错认真思考动态规划的边界设置&#xff0c;不是机械地设置1或0 动态转移方程&#xff1a; dp[i][j] dp[i-1][j]*j/n dp[i-1][j-1]*(n-j1)/n;参考代码 #include<bits/stdc.h> using namespace std;int…

ASP.NET Core Web API 最佳实践指南

原文地址&#xff1a; ASP.NET-Core-Web-API-Best-Practices-Guide介绍当我们编写一个项目的时候&#xff0c;我们的主要目标是使它能如期运行&#xff0c;并尽可能地满足所有用户需求。但是&#xff0c;你难道不认为创建一个能正常工作的项目还不够吗&#xff1f;同时这个项目…

蓝桥杯 砝码称重

试题&#xff1a; 思路&#xff1a; 经典的0-1背包问题&#xff0c;这题坑的地方在于方案数会超过边界&#xff0c;当发现当前重量可行时&#xff0c;直接归为1&#xff0c;防止dp数组累加时溢出。或者最后统计的时候&#xff0c;将判断条件从if(dp[n][i])>0改为if(dp[n][i…

[小技巧]你真的了解C#中的Math.Round么?

今天在某.NET Core 群中看到有人在问Math.Round的问题。其实这个问题之前有很多人遇到了&#xff0c;在此总结一下。开发者为了实现小数点后 2 位的四舍五入&#xff0c;编写了如下代码&#xff0c;var num Math.Round(12.125, 2);代码非常的简单&#xff0c;开发者实际得到的…