EFCore 实现 CodeFirst 通过模型生成数据库表时自动携带模型及字段注释信息

小技巧 EntityFrameworkCore 实现 CodeFirst 通过模型生成数据库表时自动携带模型及字段注释信息
今天分享自己在项目中用到的一个小技巧,就是使用 EntityFrameworkCore 时我们在通过代码去 Update-Database 生成数据库时如何自动将代码模型上的注释和字段上的注释携带到数据库中,方便后续在数据库直接查看各个表和各个字段的含义。
实现效果如下:
可以看到我们每张表都有明确的注释信息
选中表进入设计模式也可以直接看到各个字段注释
在查看表数据的时候,鼠标放在字段栏上同样也可以显示我们为字段设置的注释信息

我上面截图用的数据库管理工具是 Navicat ,各个数据库工具的呈现UI方式可能有所不同。
熟悉微软官方 EntityFrameworkCore 文档的小伙伴这个时候肯定会想到下面两个东西


当然直接为表或者模型手动指定 Comment 属性就可以实现我们上面的效果了,但是我们想要的并不是这样,因为我们在开发过程中往往给代码已经写过一次注释了,像下面的类

我们其实已经为 TOrder 模型写过注释了,甚至他内部的每个字段我们都写了注释,这样写注释的好处在于外部代码调用类时在代码编辑器中引用到模型或者字段时都可以显示注释信息出来,方便后续的代码维护。

有过同样经历的小伙伴这时候肯定就会想到,这边的注释没法直接带入数据库,我们今天要解决的就是这个问题,将代码上的注释自动赋值给 Comment 属性实现自动生成数据库表和字段的注释。
想要实现这点,首先我们需要为放置数据库模型类的代码类库启用 XML 文件生成,同时设置取消 1591 的警告,这个操作如果配置过 WebAPI Swagger 文档的小伙伴肯定很熟悉,其实都是一样的目的,就是为了项目在生成时自动生成模型的注释信息到XML文件中,因为注释信息我们的代码在编译的时候是会直接忽略的,所以并不能通过代码的某个属性来获取写在注释中的信息,所以我们选择开启 XML 描述文件生成,然后通过解析这个文件就可以获取到我们想要的注释信息。
可以在 visual studio 中选中类库右击属性,调整如下两个值

也可以直接选中类库后右击选择标记项目文件,编辑如下信息
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <NoWarn>1591</NoWarn></PropertyGroup><PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> <NoWarn>1591</NoWarn></PropertyGroup>
准备工作完成之后,接下来是我们的 GetEntityComment 方法,这是一个静态方法,用于解析 XML 文件获取指定类和字段的注释,代码如下,我这里直接将这个方法写在了 DatabaseContext 里面,大家可以按照自己的喜好放置。
其中 path 就是我们类库文档xml文件的位置,我这里默认是项目当前目录下的,文件默认名称就是类库的名称,我这里是 Repository.xml ,大家需要按照自己的实际情况进行调整。
using System.Xml;namespace Repository.Database{ public class DatabaseContext : DbContext
{ public static string GetEntityComment(string typeName, string? fieldName = null, List<string>? baseTypeNames = null)
{ var path = Path.Combine(AppContext.BaseDirectory, "Repository.xml");
XmlDocument xml = new();
xml.Load(path);
XmlNodeList memebers = xml.SelectNodes("/doc/members/member")!;
Dictionary<string, string> fieldList = new(); if (fieldName == null)
{ var matchKey = "T:" + typeName; foreach (object m in memebers)
{ if (m is XmlNode node)
{ var name = node.Attributes!["name"]!.Value; var summary = node.InnerText.Trim(); if (name == matchKey)
{
fieldList.Add(name, summary);
}
}
} return fieldList.FirstOrDefault(t => t.Key.ToLower() == matchKey.ToLower()).Value ?? typeName.ToString().Split(".").ToList().LastOrDefault()!;
} else
{ foreach (object m in memebers)
{ if (m is XmlNode node)
{ string name = node.Attributes!["name"]!.Value; var summary = node.InnerText.Trim(); var matchKey = "P:" + typeName + "."; if (name.StartsWith(matchKey))
{
name = name.Replace(matchKey, "");
fieldList.Remove(name);
fieldList.Add(name, summary);
} if (baseTypeNames != null)
{ foreach (var baseTypeName in baseTypeNames)
{EFCore 实现 CodeFirst 通过模型生成数据库表时自动携带模型及字段注释信息
声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。如若本站内容侵犯了原著者的合法权益,可联系本站删除。



