实现业务数据的同步迁移 · 思路一

(好雨知时节,大雨 _ _ _)

时不时的呢,会有小伙伴问我这样的问题:

1、群主,你的.tsv文件是如何生成的?

2、在线项目数据和种子数据的不一样,可以下么?

3、如果我本地的数据开发好了,如何把新的数据迁到生产环境呢?

01

PART

设计思路

这几个问题还是问了一段时间后,我感觉是时候需要考虑考虑了,之前一直比较懒或者没有很好的办法去处理这个问题,其实今天的办法也不是最完美的,所以我叫思路一,如果有好的思路欢迎留言和建议,有奖励哟。

今天就暂时先说说这个简单的方案吧,比较简单,就是把数据从一个DB,迁到另一个DB,然后增加一个输出tsv的功能,看似很简单,还是用到了一些知识点的:

1、多表联合,这个是基础,任何ORM都支持;

2、读写分离,但是有2个前提,下文会具体说;

3、事务处理,保证数据一致性嘛;

那下边就具体说说,如何来实现。

02

PART

开发流程

代码不是很多,相信一遍就能看懂。

1、获取集合内完整数据

这里用到了多表联合查询,毕竟SqlSugar不像EFCore那样,可以一次性就把子属性给全部查询出来,感觉就像聚合一样,那在SqlSugar中的写法有两种,官方默认的是Mapper好一些

/// <summary>
/// 查询出角色-菜单-接口关系表全部Map属性数据
/// </summary>
/// <returns></returns>
public async Task<List<RoleModulePermission>> GetRMPMaps()
{return await Db.Queryable<RoleModulePermission>().Mapper(rmp => rmp.Module, rmp => rmp.ModuleId).Mapper(rmp => rmp.Permission, rmp => rmp.PermissionId).Mapper(rmp => rmp.Role, rmp => rmp.RoleId).Where(d => d.IsDeleted == false).ToListAsync();
}

PS:这里我不想再讨论各种ORM的孰优孰劣了,那是小孩纸才会干的事儿,我项目EFCore也用,Dapper也会,就酱吧。

2、开启数据库读写分离模式

既然要数据库迁移,肯定是需要一个DB转移到另一个DB,因为我们的项目正好已经实现了读写分离模式,那正好利用这个机制,主库为写,所以配置为新库,从库为读,所以配置为旧库。结果是这样的:

这里要注意四点:

1、既然要迁移数据,那新库只生成表结构就行,不用初始化数据,False;

2、设置主库的ConnID;

3、开启CQRSEnabled开关,并配置主从库地址;

4、主从库数据库类型一致,不然会报错,毕竟不是多库模式;

千万记得新库是用来写的,所以是主库。

那最后启动项目结果是这样的:

3、开始迁移

万事俱备,只欠东风了,这一步就是要迁移数据逻辑了。其实整个项目核心的就是权限聚合部分了,涉及到了四个表:

角色表、菜单表、接口表、关系表。

因为系统用的是整型的自增主键ID,所以要考虑好关系表中,rid、mid、pid的值,要与对应表的id是一致的,如果你一直用的的GUID字符串的话,就不用考虑这个问题,无脑的数据迁移就行.

那现在要保证关系表的id问题,我是这么写的,在MigrateController.cs中:

 /// <summary>/// 获取权限部分Map数据(从库)/// 迁移到新库(主库)/// </summary>/// <returns></returns>[HttpGet]public async Task<MessageModel<string>> DataMigrateFromOld2New(){var data = new MessageModel<string>() { success = true, msg = "" };if (_env.IsDevelopment()){try{// 获取权限集合数据 var rmps = await _roleModulePermissionServices.GetRMPMaps();// 当然,你可以做个where查询//rmps = rmps.Where(d => d.ModuleId > 88).ToList();// 开启事务,保证数据一致性_unitOfWork.BeginTran();var rid = 0;var pid = 0;var mid = 0;var rpmid = 0;// 注意信息的完整性,不要重复添加,确保主库没有要添加的数据foreach (var item in rmps){// 角色信息,防止重复添加,做了判断if (item.Role != null){var isExit = (await _roleServices.Query(d => d.Name == item.Role.Name && d.IsDeleted == false)).FirstOrDefault();if (isExit == null){rid = await _roleServices.Add(item.Role);Console.WriteLine($"Role Added:{item.Role.Name}");}else{rid = isExit.Id;}}// 菜单if (item.Permission != null){pid = await _permissionServices.Add(item.Permission);Console.WriteLine($"Permission Added:{item.Permission.Name}");}// 接口if (item.Module != null){mid = await _moduleServices.Add(item.Module);Console.WriteLine($"Module Added:{item.Module.LinkUrl}");}// 关系if (rid > 0 && pid > 0 && mid > 0){rpmid = await _roleModulePermissionServices.Add(new RoleModulePermission(){IsDeleted = false,CreateTime = DateTime.Now,ModifyTime = DateTime.Now,ModuleId = mid,PermissionId = pid,RoleId = rid,});Console.WriteLine($"RMP Added:{rpmid}");}}_unitOfWork.CommitTran();data.success = true;data.msg = "导入成功!";}catch (Exception){_unitOfWork.RollbackTran();}}else{data.success = false;data.msg = "当前不处于开发模式,代码生成不可用!";}return data;}

逻辑很简单,就是获取到整体数据后,一个个添加到新库里,然后再添加关系表,保证数据的完整性,然后用事务,如果出错,可以回滚,保证一致性。

4、查看结果

到了这里,基本就没有问题了,可以看到数据已经完成了迁移:

(迁移过程,输出到控制台)

(数据库查看新库,已经有了数据)

这里完全不用胆小你的生产数据库是否已经有数据了,无论有没有,添加的权限关系表的id,也一定会和三个子表是一一对应的,且id自增,没问题。

关于其他用户表,博客表肯定不需要迁移吧,这些本地环境肯定是没有的。

那迁移完了数据,如何生成到tsv文件里呢,请往下看。

03

PART

输出到文件

那现在我们的新库有了数据,我们就可以切换到单库模式来从新库里获取数据,然后生成到tsv文件里

 [HttpGet]public async Task<MessageModel<string>> SaveData2TsvAsync(){var data = new MessageModel<string>() { success = true, msg = "" };if (_env.IsDevelopment()){try{// 取出数据,序列化,自己可以处理判空var rolesJson = JsonConvert.SerializeObject(await _roleServices.Query(d => d.IsDeleted == false));FileHelper.WriteFile(Path.Combine(_env.WebRootPath, "BlogCore.Data.json", "Role_New.tsv"), rolesJson, Encoding.UTF8);var permissionsJson = JsonConvert.SerializeObject(await _permissionServices.Query(d => d.IsDeleted == false));FileHelper.WriteFile(Path.Combine(_env.WebRootPath, "BlogCore.Data.json", "Permission_New.tsv"), permissionsJson, Encoding.UTF8);var modulesJson = JsonConvert.SerializeObject(await _moduleServices.Query(d => d.IsDeleted == false));FileHelper.WriteFile(Path.Combine(_env.WebRootPath, "BlogCore.Data.json", "Modules_New.tsv"), modulesJson, Encoding.UTF8);var rmpsJson = JsonConvert.SerializeObject(await _roleModulePermissionServices.Query(d => d.IsDeleted == false));FileHelper.WriteFile(Path.Combine(_env.WebRootPath, "BlogCore.Data.json", "RoleModulePermission_New.tsv"), rmpsJson, Encoding.UTF8);}catch (Exception){}data.success = true;data.msg = "生成成功!";}else{data.success = false;data.msg = "当前不处于开发模式,代码生成不可用!";}return data;}

结果我就不展示了,自己试试就可以了。

思考与总结

从上边的代码中,我们可以看出来,因为框架已经集成了很多重要的功能,比如读写分离和事务处理,所以代码还是比较简单的,如果自己从0开始写,还是比较麻烦的。

现在还有一个问题需要思考下,如果实现不同类型数据库的生成,这里也是两种办法:

1、使用框架的多库模式,先从库1获取数据,然后切换数据库,再生成到库2;

2、可以生成到tsv文件里做个跳板,这不过这里有一个问题,就是关系表的id如果不一样,一定会混乱的,所以这个时候又说到了主键用INT还是GUID的问题了,自己处理吧。

还是欢迎大家多多提意见吧,如何对业务数据进行同步迁移,是一个好课题。

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

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

相关文章

Interpreter(解释器)--类行为型模式

Interpreter&#xff08;解释器&#xff09;–类行为型模式 一、意图 给定一个语言&#xff0c;定义它的文法的一种表示&#xff0c;并定义一个解释器&#xff0c;这个解释器使用该表示来解释语言中的句子。 二、动机 1.在软件构建过程中&#xff0c;如果某一特定领域的问题比…

基于.NetCore3.1系列 —— 认证授权方案之授权揭秘 (下篇)

一、前言回顾&#xff1a;基于.NetCore3.1系列 —— 认证授权方案之授权揭秘 (上篇)在上一篇中&#xff0c;主要讲解了授权在配置方面的源码&#xff0c;从添加授权配置开始&#xff0c;我们引入了需要的授权配置选项&#xff0c;而不同的授权要求构建不同的策略方式&#xff0…

Iterator(迭代器)--对象行为模式

Iterator&#xff08;迭代器&#xff09;–对象行为模式 一、意图 提供一种方法顺序访问一个聚合对象的各个元素&#xff0c;而又不需暴露该对象的内部结构。 二、动机 1.在软件构建过程中&#xff0c;集合对象内部结构常常变化各异。但对于这些集合对象&#xff0c;我们希望…

Blazor带我重玩前端(三)

VS自带的Blazor模板介绍需要升级VS2019以及.NET Core到最新版&#xff08;具体的最低支持&#xff0c;我已经忘了&#xff0c;总是越新支持的就越好&#xff09;&#xff0c;以更好的支持自己开发Blazor项目。使用VS创建Blazor WebAssembly项目搜索Blazor模板选择Blazor WebAss…

[mybatis]Configuration XML_environments

enviroments transactionManager There are two TransactionManager types (i.e. type"[JDBC|MANAGED]") that are included with MyBatis: • JDBC – This configuration simply makes use of the JDBC commit and rollback facilities directly. It relies on the…

Mediator(中介者)--对象行为型模式

Mediator&#xff08;中介者&#xff09;–对象行为型模式 一、意图 用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用&#xff0c;从而使其耦合松散&#xff0c;而且可以独立地改变它们之间的交互。 二、动机 1.在软件构建过程中&#xff0c;经常…

[mybatis]Configuration XML_mappers

mappers 将sql映射注册到全局配置中 mapper 注册一个sql映射 resource:引用类路径下的sql映射文件url:引用网络路径或者磁盘路径下的sql映射文件class:引用(注册)接口 1.有sql映射文件&#xff0c;映射文件名必须和接口同名&#xff0c;并且放在与接口同一目录下&#xff1b;…

Memento(备忘录)--对象行为型模式

Memento&#xff08;备忘录&#xff09;–对象行为型模式 一、意图 在不破坏封装性的前提下&#xff0c;捕获一个对象的内部状态&#xff0c;并在该对象之外保持这个状态。这样以后就可将该对象恢复到原先保存的状态。 二、动机 1.在软件构建过程中&#xff0c;某些对象的状态…

IBM、甲骨文、CNCF 就谷歌对 Istio 治理的处理提出抗议

近日来 Istio 商标转让、IBM 抗议谷歌违背承诺未将 Istio 捐献给 CNCF 的事情闹的沸沸扬扬。Google 宣布将 Istio 商标转让给 Open Usage Commons 组织IBM 声明对 Google 违背承诺未将 Istio 贡献给 CNCF 表示失望下面是据 TheRegister 的报道&#xff1a;谷歌创建了一个开放使…

Observer(观察者)--对象行为型模式

Observer&#xff08;观察者&#xff09;–对象行为型模式 一、意图 定义对象间的一种一对多的依赖关系&#xff0c;当一个对象的状态发生变化时&#xff0c;所有的依赖于它的对象都得到通知并被自动更新。 二、动机 1.在软件构建过程中&#xff0c;我们需要为某些对象建立一…

【今天下午活动】从 HelloWorld 到 AntDesign,Blazor 将 .NET 带到现代前端圈

Blazor 是一个 Web UI 框架&#xff0c;可通过 WebAssembly 在任意浏览器中运行 .Net 。Blazor 旨在简化快速的单页面 .Net 浏览器应用的构建过程&#xff0c;它虽然使用了诸如 CSS 和 HTML 之类的 Web 技术&#xff0c;但它使用 C&#xff03;语言和 Razor 语法代替 JavaScrip…

[mybatis]sqlSessionFactory.openSession()

第一个是不会自动提交的 第二个带参数的是会自动提交的

State(状态)--对象行为型模式

State&#xff08;状态&#xff09;–对象行为型模式 一、意图 允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。 二、动机 1.在软件构建过程中&#xff0c;某些对象的状态如果改变&#xff0c;其行为也会随之而发生变化&#xff0c;比如文档处于只…

推荐一个Asp.Net Core工具库

Masuit.Tools开源地址https://github.com/XiLife-OSPC/Masuit.Tools包含一些常用的操作类&#xff0c;大都是静态类&#xff0c;加密解密&#xff0c;反射操作&#xff0c;硬件信息&#xff0c;字符串扩展方法&#xff0c;日期时间扩展操作&#xff0c;大文件拷贝&#xff0c;图…

Strategy(策略)--对象行为型模式

Strategy&#xff08;策略&#xff09;–对象行为型模式 一、意图 定义一系列的算法&#xff0c;把它们一个个封装起来&#xff0c;并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。 二、动机 1.在软件构建过程中&#xff0c;某些对象使用的算法可能多种多…

12个Visual Studio调试效率技巧

在这篇文章中&#xff0c;我们假定读者了解VS基本的调试知识&#xff0c;如&#xff1a;F5 开始使用调试器运行程序F9 在当前行设置断点F10 运行到下一个断点处F5 从被调试的已停止程序恢复执行F11 步进到函数内&#xff08;如果当前程序指针指向一个函数&#xff09;F10 步过函…

Template Method(模板方法)--类行为型模式

Template Method&#xff08;模板方法&#xff09;–类行为型模式 一、意图 定义一个操作中的算法的骨架&#xff0c;而将一些步骤延迟到子类中。TemplateMethod使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 二、动机 1.在软件构建过程中&#xff0c;对…

骚年快答 | 微服务架构中的BFF到底是啥?

【答疑解惑】| 作者 / Edison Zhou这是恰童鞋骚年的第263篇原创内容昨天的骚年快答《技术中台与业务中台都是啥玩意》一文中留下一个问题&#xff1a;BFF是啥&#xff1f;为啥在API网关和业务中台之间加入了一层BFF&#xff1f;考虑到在实际工作中&#xff0c;我的大部分同事都…