Day 2 Abp框架下,MySQL数据迁移时,添加表和字段注释

后端采用Abp框架,当前最新版本是7.4.0。

数据库使用MySQL,在执行数据库迁移时,写在Domain层的Entity类上的注释通通都没有,这样查看数据库字段的含义时,就需要对照代码来看,有些不方便。今天专门来解决这个问题。

还是一顿搜索,发现了两个方案:

abp 框架拓展mysql 迁移:增加数据库表和列备注

EFcore+MySql 数据迁移的时候,怎么给表结构加注释?


 

上述两篇文章,

第一篇重载 MySqlMigrationsSqlGenerator 来实现加注释,但是字段注释是通过Description属性来获取的,这样字段上就要注释和Description重复写两遍。

第二篇直接通过工具,读取xml文档,生成 HasComment相关代码,每次都需要手动修改DbContext代码。

都不是特别完美,所以结合一下看看。具体方案还是重载MySqlMigrationsSqlGenerator,但是通过读取xml来获取信息。

首先是SqlGenerator:

/// <summary>
/// 拓展迁移操作:增加数据表和列备注
/// </summary>
public class MyMigrationsSqlGenerator : MySqlMigrationsSqlGenerator
{public MyMigrationsSqlGenerator(MigrationsSqlGeneratorDependencies dependencies,IMigrationsAnnotationProvider migrationsAnnotations,ICommandBatchPreparer commandBatchPreparer,IMySqlOptions mySqlOptions): base(dependencies, commandBatchPreparer, mySqlOptions){}protected override void Generate(MigrationOperation operation, IModel model, MigrationCommandListBuilder builder){base.Generate(operation, model, builder);if (operation is CreateTableOperation || operation is AlterTableOperation)CreateTableComment(operation, model, builder);if (operation is AddColumnOperation || operation is AlterColumnOperation)CreateColumnComment(operation, model, builder);}/// <summary>/// 创建表注释/// </summary>/// <param name="operation"></param>/// <param name="builder"></param>private void CreateTableComment(MigrationOperation operation, IModel model, MigrationCommandListBuilder builder){string tableName = string.Empty;string description = string.Empty;if (operation is AlterTableOperation){var t = operation as AlterColumnOperation;tableName = (operation as AlterTableOperation).Name;}if (operation is CreateTableOperation){var t = operation as CreateTableOperation;var addColumnsOperation = t.Columns;tableName = t.Name;foreach (var item in addColumnsOperation){CreateColumnComment(item, model, builder);}}//description = DbDescriptionHelper.GetDescription(tableName.Replace(jingdianConsts.DbTablePrefix, ""));description = GetDescription(tableName, null);if (tableName.IsNullOrWhiteSpace())throw new Exception("表名为空引起添加表注释异常.");var sqlHelper = Dependencies.SqlGenerationHelper;builder.Append("ALTER TABLE ").Append(sqlHelper.DelimitIdentifier(tableName)).Append(" COMMENT ").Append("'").Append(description).Append("'").AppendLine(sqlHelper.StatementTerminator).EndCommand();}/// <summary>/// 创建列注释/// </summary>/// <param name="operation"></param>/// <param name="builder"></param>private void CreateColumnComment(MigrationOperation operation, IModel model, MigrationCommandListBuilder builder){//alter table a1log modify column UUID VARCHAR(26) comment '修改后的字段注释';string tableName = string.Empty;string columnName = string.Empty;string columnType = string.Empty;string description = string.Empty;if (operation is AlterColumnOperation){var t = (operation as AlterColumnOperation);columnType = t.ColumnType;}if (operation is AddColumnOperation){var t = (operation as AddColumnOperation);columnType = t.ColumnType;description = GetDescription(tableName, columnName);}if (columnName.IsNullOrWhiteSpace() || tableName.IsNullOrWhiteSpace() || columnType.IsNullOrWhiteSpace())throw new Exception("列名为空或表名为空或列类型为空引起添加列注释异常." + columnName + "/" + tableName + "/" + columnType);var sqlHelper = Dependencies.SqlGenerationHelper;builder.Append("ALTER TABLE ").Append(sqlHelper.DelimitIdentifier(tableName)).Append(" MODIFY COLUMN ").Append(columnName).Append(" ").Append(columnType).Append(" COMMENT ").Append("'").Append(description).Append("'").AppendLine(sqlHelper.StatementTerminator).EndCommand();}private string GetDescription(string tableName, string? columnName){var type = TableCommentRegister.Types[tableName];if (type == null){return string.Empty;}string xmlPath = type.Module.Name.Replace("dll","xml");XmlDocument xml = new XmlDocument();xml.Load(xmlPath);var classNode = xml.SelectSingleNode(($"//member[@name='T:{type.FullName}']"));if (classNode == null){return string.Empty;}if (columnName == null){return classNode.InnerText.Trim();}else{var propertyNode = xml.SelectSingleNode(($"//member[@name='P:{type.FullName}.{columnName}']"));if (propertyNode == null){return string.Empty;}return propertyNode.InnerText.Trim();}}
}

这里面有一个点,生成Sql时,只知道table name和column name,一般情况下列名就是属性名,可以不考虑,但是表名和类名可能会有差异,比如前后缀之类的。参考1中,就是直接做替换,我考虑还是做了一个静态字典对象,把表名和类名做了一个映射,具体如下:

/// <summary>
/// 数据表注册器
/// </summary>
public static class TableCommentRegister
{public static Dictionary<string, Type> Types { get; set; } = new Dictionary<string, Type>();/// <summary>/// 配置实体对应的数据表,同时注册类型,用于后续生成备注/// </summary>/// <typeparam name="T">实体类型</typeparam>/// <param name="builder"></param>/// <param name="tableName">数据表名</param>public static void ToTableWithComment<T>(this EntityTypeBuilder<T> builder, string tableName) where T : class{builder.ToTable(tableName);Types.TryAdd(tableName, typeof(T));}
}

然后在DbContext类中,针对表的处理代码如下:

 builder.Entity<Company>(b =>{string tableName = Consts.DbTablePrefix + "Company";b.ToTableWithComment(tableName);b.ConfigureByConvention(); //auto configure for the base class props});

就是把之前的 ToTable 改成 ToTableWithComment 就可以了。

最后,需要修改DbSchemaMigrator类,把SqlGenerator注册进去。这里我就简单粗暴的复制了一下DbContextFactory类。因为DbContextFactory代码注释则表明了其只是用于EF Core console commands,在Abp的DbMigrator程序中不起作用。

DbSchemaMigrator类中,Abp 脚手架代码应该是这样的:

public async Task MigrateAsync()
{/* We intentionally resolving the XiuYuanDbContext* from IServiceProvider (instead of directly injecting it)* to properly get the connection string of the current tenant in the* current scope.*/await _serviceProvider.GetRequiredService<XiuYuanDbContext>().Database.MigrateAsync();
}

修改如下:

public async Task MigrateAsync()
{    await CreateDbContext()            .Database.MigrateAsync();
}public xxxDbContext CreateDbContext()
{xxxEfCoreEntityExtensionMappings.Configure();var configuration = BuildConfiguration();var connection = configuration.GetConnectionString(xxxConsts.DbSchema);var builder = new DbContextOptionsBuilder<xxxDbContext>().UseMySql(connection, ServerVersion.AutoDetect(connection), o => o.SchemaBehavior(MySqlSchemaBehavior.Ignore))// 注意这里的ReplaceService.ReplaceService<IMigrationsSqlGenerator, MyMigrationsSqlGenerator>();return new xxxDbContext(builder.Options);
}private static IConfigurationRoot BuildConfiguration()
{var builder = new ConfigurationBuilder().AddJsonFile("appsettings.json", optional: false);return builder.Build();
}

至此,所有基础性工作都完成了,后面再添加领域模型时,记得把ToTable改成ToTableWithComment即可。

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

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

相关文章

优思学院|六西格玛证书怎么考?7个步骤助你马上取得

在当今竞争激烈的职场环境中&#xff0c;持有六西格玛证书可以为您的职业生涯增添亮点。 事实上&#xff0c;六西格玛认证的机构还是挺多&#xff0c;首先&#xff0c;是独立的认证组织授予的认证&#xff0c;例如比如美质协、国际精益六西格玛研究所&#xff08;ILSSI&#x…

Angular-01:基本架构

各种学习后的知识点整理归纳&#xff0c;非原创&#xff01; ① 概述 angular是一个使用HTML、CSS、TypeScript构建的客户端应用的框架&#xff0c;用来构建单页面应用程序。是一个重量级的框架&#xff0c;内部集成了大量开箱即用的功能模块。是为大型应用开发而设计&#xf…

百度Comate SaaS版本正式发布,助力开发者加速研发过程

百度Comate是基于文心大模型的智能代码助手&#xff0c;让开发者的编码更快、更好、更简单&#xff0c;为开发者自动生成完整的、且更符合实际研发场景的代码行或整个代码块&#xff0c;帮助每一位开发者轻松完成研发任务。10月17日召开的百度世界大会上&#xff0c;百度CTO王海…

uni-app小程序,uview-ui组件样式无法穿透修改的解决办法

1.首先设置以下选项.该选项的作用是让微信小程序允许样式穿透. 在需要改动的文件内加上 options: { styleIsolation: shared } 2.然后再使用vue的样式穿透写法. ::v-deep .类样式{} 或者 /deep/ .类样式{}

非父子组件通信-发布订阅模式

发布订阅模式其实与vue无关&#xff0c;完全是ES6的代码&#xff0c;但是它可以通过这种模式实现非父子组件的通信 store.js文件 首先创建一个store.js文件&#xff0c;用于提供发布与订阅方法 export default {datalist: [], //存放带一个参数的函数集合//订阅subscribe(fu…

使用非空断言解决Typescript报错:对象可能为 “null“

现象如下&#xff1a; 解决办法&#xff1a;在报错的属性后面加惊叹号&#xff01;&#xff0c; 也就是非空断言 问题解决&#xff1a;

挑战没有免费的午餐定理?南洋理工提出扩散模型增强方法FreeU

论文名称&#xff1a;FreeU: Free Lunch in Diffusion U-Net 文章链接&#xff1a;https://arxiv.org/abs/2309.11497 代码仓库&#xff1a;https://github.com/ChenyangSi/FreeU 项目主页&#xff1a;https://chenyangsi.top/FreeU 机器学习领域中一个著名的基本原理就是“没…

MySQL - mvcc

mvcc 是什么&#xff1f; MVCC&#xff08;多版本并发控制&#xff09;是一种数据库并发控制机制&#xff0c;旨在提高数据库的并发性&#xff0c;避免锁定操作&#xff0c;从而减少等待和提高性能。MVCC 主要解决数据库读写操作之间的线程安全问题。 MVCC 主要有两种读取数据…

【web前端】web前端设计入门到实战第二弹——面试题总结+答案

这里写目录标题 一、选择题二、填空题 一、选择题 1、表格的主要作用是&#xff08; B &#xff09;。 A.网页排版布局 B.显示数据 C.处理图像 D.优化网站 2、如果表格的边框不显示&#xff0c;应设置border的值为&#xff08; B &#xff09;。 A.1 B.0 C.2 D.3 3、定义单元格…

RetentionPolicy枚举类

包名package java.lang.annotation 作用 注释保留策略。此枚举类型的常量描述用于保留注释的各种策略。它们被使用与&#xff5b; Retention&#xff5d;元注释类型一起指定注释要保留多长时间。 属性 SOURCE编译器将丢弃注释。CLASS注释将由编译器记录在类文件…

threejs(3)-详解材质与纹理

一、Matcap(MeshMatcapMaterial)材质原理与应用 Matcap是一张含有光照信息的贴图&#xff0c;通常是直接截取材质球截图来使用。因此Matcap可以很好的模拟静止光源下的光照效果。 最直接的方式就是直接使用在View空间下的模型法向量的xy分量去采样Matcap。 另外还有一种常见…

EPPlus库的安装和使用 C# 中 Excel的导入和导出

安装 工具栏->NuGet 包管理器->管理解决方案的NuGet程序包 安装到当前项目中 使用 将 DataGridView 数据导出为Excel 首先&#xff0c;需要将数据DataGridView对象转换为DataTable private void btnExport_Click(object sender, EventArgs e) {// 1.将当前页面的data…

基于Raft解决“幽灵复现”问题

3.1 关于Raft日志恢复 首先,我们聊一下Raft的日志恢复,在 Raft 中,每次选举出来的Leader一定包含已经Committed的数据(抽屉原理,选举出来的Leader是多数中数据最新的,一定包含已经在多数节点上Commit的数据),新的Leader将会覆盖其他节点上不一致的数据。虽然新选举出来…

json-server工具准备后端接口服务环境

1.安装全局工具json-server&#xff08;全局工具仅需要安装一次&#xff09; 官网&#xff1a;json-server - npm 点击Getting started可以查看使用方法 在终端中输入yarn global add json-server或npm i json-server -g 如果输入json-server -v报错 再输入npm install -g j…

Elasticsearch之mapping

文章目录 以显式的方式创建一个映射查看某个具体索引的mapping定义向已存在的映射中添加一个新的属性查看映射中指定字段的定义信息更新已存在映射的某个字段 1、 官方文档地址 2、 字段类型 1、定义&#xff1a;映射是定义文档及其包含的字段如何存储和索引的过程。 2、每个…

电影评分数据分析案例-Spark SQL

# cording:utf8from pyspark.sql import SparkSession from pyspark.sql.types import IntegerType, StringType, StructType import pyspark.sql.functions as Fif __name__ __main__:# 0.构建执行环境入口对象SparkSessionspark SparkSession.builder.\appName(movie_demo)…

typedef __packed struct 中的__packed意义

typedef __packed struct 是C语言中用于定义紧凑结构体的语法。__packed关键字用于告诉编译器不要为结构体成员添加填充字节&#xff0c;从而使得结构体的大小更加紧凑。typedef关键字用于为数据类型定义一个新的名称。 下面是一个使用__packed和typedef的示例代码&#xff1a…

【网络爬虫 | Python】数字货币ok链上bitcoin大额交易实时爬取,存入 mysql 数据库

文章目录 一、网站分析二、js 逆向获取 X-Apikey三、python 调用 js 获取 X-Apikey四、python 爬虫部分五、mysql 数据库、日志、配置文件、目录结构六、结尾 一、网站分析 oklink&#xff1a;https://www.oklink.com/ btc 大额交易&#xff1a;https://www.oklink.com/btc/tx-…

蜂鸟物流开放平台-配送系统

文章目录 引言API 接入指南1.1 Maven 引入 SDK1.2 pom.xml包依赖冲突解决引言 API 接入指南 https://gitee.com/ash_floating_around/anubis-openapi-sdk 上线前将 Config 中 IS_SANDBOX 值设为 false,并填写正式环境的 APP_ID 和 SECRET_KEY。 1.1 Maven 引入 SDK <d…

解决 edge 浏览器开发者工具出不来的问题

文章目录 猜测原因问题现象尝试过程最终解决办法C盘爆满解决经过&#xff08;拆东墙补西墙&#xff09; 猜测原因 windows 系统更新导致电脑管家C盘迁移导致&#xff08;我C盘爆满了&#xff0c;每天提醒看着膈应&#xff0c;想着清理一下&#xff09; 问题现象 按F12 和 右键…