Code Fisrt 更新注释到mysql数据库
背景:
从java项目翻到.net core 项目,将java的实体转换成.net 的实体,然后使用 ef tool 直接更新到数据库
命令如下:
Enable-Migrations -EnableAutomaticMigrations
Add-Migration InitialCreate
Update-Database -Verbose
更新的时候会遇到几个问题
1. 外键关系:
因为我的项目中使用Guid做关联,所有就没有使用外键,如果要做外键关联可以参考这篇文章
2.注释无法更新到数据库
如果一个个注释都手动添加到数据库,几十张表,会不会很蛋疼:
然后看网上给出的思路,根据生成的xml 获取注释,更新到数据库
如果大家有什么工具,希望大家分享下 -,-,
下面简单介绍下思路:
两个项目
1:DbContext项目,就是model-first中对应数据库实体的项目,一般都是单独放在一个项目中
2:控制台程序,您也可以做成web,或者窗体,这边我为了省事做了控制台程序
(不知道为什么,博客园提示无法上传图片,下次补齐图片,先用文字描述。。。)
控制台程序添加对DbContext项目的引用,
右击DbContext项目,在生成中的 勾选 输出 “xml 文档文件(X)” bin\Debug\netcoreapp2.1\***.xml ,这个xml文件包含了项目中实体的注释
你大概可以看到xml文件中的内容大概是如下
<member name="T:TmcService.Core.Model.TestTable"> <summary> 用于测试 </summary> </member> <member name="P:TmcService.Core.Model.TmcSuppliers.SupplierCode"> <summary> 主键 </summary> </member> <member name="P:TmcService.Core.Model.TmcSuppliers.Name"> <summary> 名称 </summary> </member>
可以看到表明 的xml节点 T:TmcService.Core.Model.TestTable
和字段的xml节点 P:TmcService.Core.Model.TmcSuppliers.Name
好了基础工作做完我们就开始下一步
1.读取xml文件,获取每一个节点,将结果集存到list中,
2.使用反射获取程序集和表的对应关系存到字典中,
代码如下,数据库操作是用的Dapper,应为数据库mysql所以用了 Pomelo.EntityFrameworkCore.MySql 在nuget都可以直接安装
代码中部分命名空间做了处理
1 namespace TmcService.GenertageAnnotationToDb 2 { 3 class Program 4 { 5 private static MySqlConnection con = new MySqlConnection("连接字符串"); 6 7 static void Main(string[] args) 8 { 9 Console.WriteLine($"如果出现两个命名空间包含相同的字符串的情况下:\n" + 10 $"类名:Cofig 命名空间:TmcService.Core.Model \n" + 11 $"类名:CofigDetail 命名空间:TmcService.Core.Model \n" + 12 $"这种情况下会发生异常,可以手动将拼接的字段生成sql脚本手动更新 \n"); 13 Console.WriteLine("按任意键更新数据库注释...\n"); 14 Console.ReadKey(); 15 try 16 { 17 Console.WriteLine("注释更新中..."); 18 UpdateAnnonation(); 19 Console.WriteLine("更新成功按任意键退出..."); 20 } 21 catch (Exception ex) 22 { 23 Console.WriteLine("更新失败 \n"); 24 Console.WriteLine(ex.ToString()); 25 } 26 Console.ReadKey(); 27 } 28 29 /// <summary> 30 /// 获取数据类名和对应的数据库表名,返回一个dic 31 /// </summary> 32 /// <returns></returns> 33 private static Dictionary<string, string> GetAllCalssMapperDbName() 34 { 35 Dictionary<string, string> keyValuePairs = new Dictionary<string, string>(); 36 37 //引用model,DbContext的dll 38 string dllName = AppDomain.CurrentDomain.BaseDirectory + @"***"; 39 Assembly assembly = Assembly.LoadFrom(dllName); 40 41 //获取数据库映射到数据库的实体类(根据情况自行处理) 42 var typies = assembly.GetTypes().Where(o => o.FullName.Contains("***") && !o.FullName.Contains("***")).ToList(); 43 44 //创建对象的实例,获取对象的属性,获取对象在数据库对应的表, 45 typies.ForEach(o => 46 { 47 Object obj = Activator.CreateInstance(o); 48 var attribute = o.GetCustomAttributes(typeof(TableAttribute), false).FirstOrDefault(); 49 if (attribute != null) 50 { 51 keyValuePairs.Add(o.FullName, ((TableAttribute)attribute).Name); 52 } 53 }); 54 return keyValuePairs; 55 } 56 57 /// <summary> 58 /// 根据根据dic 匹配类和表关系,将字段标注更新到数据库 59 /// </summary> 60 private static List<AnnonationModel> GerAnnonationFromXmlDoc() 61 { 62 var keyValuePairs = GetAllCalssMapperDbName(); 63 64 XmlDocument xmlDoc = new XmlDocument(); 65 xmlDoc.Load("dbcontext.xml"); 66 var list = xmlDoc.SelectSingleNode("doc").SelectSingleNode("members"); 67 var annonationList = new List<AnnonationModel>(); 68 foreach (var item in list) 69 { 70 AnnonationModel annonationmodel = new AnnonationModel(); 71 var member = (XmlNode)item; 72 var annotation = member.SelectSingleNode("summary"); 73 string summary = string.Empty; 74 var attr = member.Attributes["name"]; 75 var attrVal = string.Empty; 76 if (attr != null) 77 { 78 attrVal = member.Attributes["name"].Value; 79 } 80 if (annotation != null) 81 { 82 summary = (annotation).InnerText; 83 } 84 annonationmodel.Annonation = summary; 85 annonationmodel.ClassName = attrVal; 86 annonationList.Add(annonationmodel); 87 } 88 return annonationList; 89 } 90 91 /// <summary> 92 /// 更新 93 /// </summary> 94 private static void UpdateAnnonation() 95 { 96 //更新数据库字段注释 97 var keyValuePairs = GetAllCalssMapperDbName(); 98 var annonationList = GerAnnonationFromXmlDoc(); 99 100 string sqls = string.Empty; 101 102 foreach (var item in keyValuePairs) 103 { 104 var className = item.Key; 105 var tableName = item.Value; 106 107 //获取注释的所有属性 108 var fields = annonationList.Where(o => o.ClassName.Contains(className)).ToList(); 109 110 StringBuilder sb = new StringBuilder(); 111 112 foreach (var o in fields) 113 { 114 if (!o.ClassName.Contains("T:")) 115 { 116 string[] str = o.ClassName.Split("."); 117 var len = str.Length; 118 var attrName = str[len - 1]; 119 //mql数据库关键字处理 120 if (attrName == "Name" || attrName == "Status") 121 { 122 attrName = "`" + attrName + "`"; 123 } 124 string sql = $" alter table {tableName} modify column {attrName} int comment'{o.Annonation}'; \n"; 125 sb.Append(sql); 126 } 127 } 128 sqls += sb.ToString(); 129 } 130 con.Execute(sqls); 131 } 132 } 133 134 public class AnnonationModel 135 { 136 public string ClassName { get; set; } 137 public string Annonation { get; set; } 138 139 } 140 }