1. 程式人生 > >【繁星Code】如何在EF將實體註釋寫入資料庫中

【繁星Code】如何在EF將實體註釋寫入資料庫中

        最近在專案中需要把各個欄位的釋義寫到資料庫中,該專案已經上線很長時間了,資料庫中的欄位沒有上千也有上百個,要是一個專案一個專案開啟然後再去找對應欄位檢視什麼意思,估計要到明年過年了。由於專案中使用EntityFramework,本身這個專案只有手動設定欄位註釋的功能,Coder平時寫程式碼的時候都懶得寫註釋,更別提能在配置資料庫的時候將註釋配置進去,所以如何在EF中自動將實體註釋寫入資料庫,減輕Coder的壓力(ru he tou lan)尤為重要。gitee地址:https://gitee.com/lbqman/Blog20210206.git 。下面進入正題。

一、實現思路

        在FluentAPI中提供了HasComment方法,如下           11       1
    /// <summary>Configures a comment to be applied to the column</summary>
2
    /// <typeparam name="TProperty"> The type of the property being configured. </typeparam>
3
    /// <param name="propertyBuilder"> The builder for the property being configured. </param>
4
    /// <param name="comment"> The comment for the column. </param>
5
    /// <returns> The same builder instance so that multiple calls can be chained. </returns>
6
    public static PropertyBuilder<TProperty> HasComment<TProperty>(
7
      [NotNull] this PropertyBuilder<TProperty> propertyBuilder,
8
      [CanBeNull] string comment)
9
    {
10
      return (PropertyBuilder<TProperty>) propertyBuilder.HasComment(comment);
11
    }
    也就是說我們要獲取到實體物件的註釋xml,然後讀取對應的欄位註釋,自動呼叫改方法即可。需要解決的問題大概有以下幾點。
  1. 如何獲取當前配置的欄位;
  2. 載入Xml,並根據欄位獲取對應的註釋;
  3. 如何將列舉的各項資訊都放入註釋中;

二、實現方法

    1.如何獲取當前配置的欄位

       在獲取xml的註釋中,需要的資訊有實體對應的型別以及對應的欄位。而包含這兩種型別的方法只有Property這個方法,該方法的出入參如下:           2       1
public virtual PropertyBuilder<TProperty> Property<TProperty>(
2
      [NotNull] Expression<Func<TEntity, TProperty>> propertyExpression);
            所以我們準備對這個方法進行改造。並且根據傳入的propertyExpression獲取欄位名稱。方法如下:           4       1
        public static PropertyBuilder<TProperty> SummaryProperty<TEntity, TProperty>(
2
            this EntityTypeBuilder<TEntity> entityTypeBuilder,
3
            Expression<Func<TEntity, TProperty>> propertyExpression)
4
            where TEntity : class
            根據表示式獲取欄位名稱如下:           10       1
        public static MemberInfo GetMember<T, TProperty>(this Expression<Func<T, TProperty>> expression)
2
        {
3
            MemberExpression memberExp;
4
            if (expression.Body is UnaryExpression unaryExpression)
5
                memberExp = unaryExpression.Operand as MemberExpression;
6
            else
7
                memberExp = expression.Body as MemberExpression;
8




9

            return memberExp?.Member;
10
        }
   

  2.載入Xml,並根據欄位獲取對應的註釋

    VS中的Xml格式不在此處過多解釋,屬性、方法等註釋可以根據規律去獲取。此處需要注意的是當欄位是從父類繼承而來並且父類屬於不同的dll時,需要獲取父類所在dll的xml註釋才行,另外列舉也需要同樣去處理。雖然獲取Xml資料的方法只在更新資料庫時才呼叫,但是還是需要使用字典將資料快取下來,方便下次快速獲取。具體程式碼如下:           204       1
   /// <summary>
2
    /// xml註釋獲取器
3
    /// </summary>
4
    internal static class SummaryXmlCacheProvider
5
    {
6
        #region TClass
7




8

        /// <summary>
9
        /// 根據型別初始化該類所在程式集的xml
10
        /// </summary>
11
        /// <typeparam name="TClass"></typeparam>
12
        internal static void InitSummaryXml<TClass>()
13
        {
14
            var assembly = Assembly.GetAssembly(typeof(TClass));
15
            SerializeXmlFromAssembly(assembly);
16
        }
17




18

        /// <summary>
19
        /// 根據型別獲取該類所在程式集的xml
20
        /// </summary>
21
        /// <typeparam name="TClass"></typeparam>
22
        /// <returns></returns>
23
        internal static Dictionary<string, string> GetSummaryXml<TClass>()
24
        {
25
            var assembly = Assembly.GetAssembly(typeof(TClass));
26
            return SummaryCache[assembly];
27
        }
28




29

        /// <summary>
30
        /// 獲取該類在xml的key
31
        /// </summary>
32
        /// <typeparam name="TClass"></typeparam>
33
        /// <returns></returns>
34
        internal static string GetClassTypeKey<TClass>()
35
        {
36
            return TableSummaryRuleProvider.TypeSummaryKey(typeof(TClass).FullName);
37
        }
38




39

        #endregion
40




41

        #region TProperty
42




43

        /// <summary>
44
        /// 根據型別以及欄位初始化該類所在程式集的xml
45
        /// </summary>
46
        /// <typeparam name="TClass"></typeparam>
47
        /// <typeparam name="TProperty"></typeparam>
48
        /// <param name="propertyExpression"></param>
49
        internal static void InitSummaryXml<TClass, TProperty>(Expression<Func<TClass, TProperty>> propertyExpression)
50
        {
51
            var propertyAssembly = GetPropertyAssembly(propertyExpression);
52
            SerializeXmlFromAssembly(propertyAssembly);
53
        }
54




55

        /// <summary>
56
        /// 根據型別以及欄位獲取該類所在程式集的xml
57
        /// </summary>
58
        /// <typeparam name="TClass"></typeparam>
59
        /// <typeparam name="TProperty"></typeparam>
60
        /// <param name="propertyExpression"></param>
61
        /// <returns></returns>
62
        internal static Dictionary<string, string> GetSummaryXml<TClass, TProperty>(
63
            Expression<Func<TClass, TProperty>> propertyExpression)
64
        {
65
            var propertyAssembly = GetPropertyAssembly(propertyExpression);
66
            return SummaryCache[propertyAssembly];
67
        }
68




69

        /// <summary>
70
        /// 獲取該類以及欄位所在xml的key
71
        /// </summary>
72
        /// <typeparam name="TClass"></typeparam>
73
        /// <typeparam name="TProperty"></typeparam>
74
        /// <param name="propertyExpression"></param>
75
        /// <returns></returns>
76
        internal static string GetPropertyTypeKey<TClass, TProperty>(
77
            Expression<Func<TClass, TProperty>> propertyExpression)
78
        {
79
            var memberName = propertyExpression.GetMember().Name;
80
            var propertyInfo = GetPropertyInfo(propertyExpression);
81
            var propertyKey =
82
                $"{propertyInfo.DeclaringType.Namespace}.{propertyInfo.DeclaringType.Name}.{memberName}";
83
            return PropertySummaryRuleProvider.PropertyTypeSummaryKey(propertyKey);
84
        }
85




86

        #endregion
87




88

        #region TEnum
89




90

        /// <summary>
91
        /// 獲取列舉欄位的描述資訊
92
        /// </summary>
93
        /// <typeparam name="TClass"></typeparam>
94
        /// <typeparam name="TProperty"></typeparam>
95
        /// <param name="propertyExpression"></param>
96
        /// <returns></returns>
97
        internal static string GetEnumPropertyDescription<TClass, TProperty>(Expression<Func<TClass, TProperty>> propertyExpression)
98
        {
99
            var propertyInfo = GetPropertyInfo(propertyExpression);
100
            if (!propertyInfo.PropertyType.IsEnum)
101
                return string.Empty;
102
            var enumType = propertyInfo.PropertyType;
103
            SerializeXmlFromAssembly(enumType.Assembly);
104
            var propertySummaryDic = SummaryCache[enumType.Assembly];
105
            var enumNames = enumType.GetEnumNames();
106
            var enumDescDic = enumType.GetNameAndValues();
107
            var enumSummaries = new List<string>();
108
            foreach (var enumName in enumNames)
109
            {
110
                var propertyEnumKey = PropertySummaryRuleProvider.EnumTypeSummaryKey($"{enumType.FullName}.{enumName}");
111
                var enumSummary = propertySummaryDic.ContainsKey(propertyEnumKey)
112
                    ? propertySummaryDic[propertyEnumKey]
113
                    : string.Empty;
114
                var enumValue = enumDescDic[enumName];
115
                enumSummaries.Add(PropertySummaryRuleProvider.EnumTypeSummaryFormat(enumValue,enumName,enumSummary));
116
            }
117




118

            return string.Join(";", enumSummaries);
119




120

        }
121




122

        #endregion
123




124

        /// <summary>
125
        /// 根據表示式獲取屬性所在的程式集
126
        /// </summary>
127
        /// <typeparam name="TClass"></typeparam>
128
        /// <typeparam name="TProperty"></typeparam>
129
        /// <param name="propertyExpression"></param>
130
        /// <returns></returns>
131
        private static Assembly GetPropertyAssembly<TClass, TProperty>(
132
            Expression<Func<TClass, TProperty>> propertyExpression)
133
        {
134
            var propertyInfo = GetPropertyInfo(propertyExpression);
135
            var propertyAssembly = propertyInfo.Module.Assembly;
136
            return propertyAssembly;
137
        }
138




139

        /// <summary>
140
        /// 根據表示式獲取欄位屬性
141
        /// </summary>
142
        /// <typeparam name="TClass"></typeparam>
143
        /// <typeparam name="TProperty"></typeparam>
144
        /// <param name="propertyExpression"></param>
145
        /// <returns></returns>
146
        private static PropertyInfo GetPropertyInfo<TClass, TProperty>(
147
            Expression<Func<TClass, TProperty>> propertyExpression)
148
        {
149
            var entityType = typeof(TClass);
150
            var memberName = propertyExpression.GetMember().Name;
151
            var propertyInfo = entityType.GetProperty(memberName, typeof(TProperty));
152
            if (propertyInfo == null || propertyInfo.DeclaringType == null)
153
                throw new ArgumentNullException($"this property {memberName} is not belong to {entityType.Name}");
154




155

            return propertyInfo;
156
        }
157




158

        /// <summary>
159
        /// 根據程式集初始化xml
160
        /// </summary>
161
        /// <param name="assembly"></param>
162
        private static void SerializeXmlFromAssembly(Assembly assembly)
163
        {
164
            var assemblyPath = assembly.Location;
165
            var lastIndexOf = assemblyPath.LastIndexOf(".dll", StringComparison.Ordinal);
166
            var xmlPath = assemblyPath.Remove(lastIndexOf, 4) + ".xml";
167




168

            if (SummaryCache.ContainsKey(assembly))

相關推薦

繁星Code如何在EF實體註釋寫入資料庫

        最近在專案中需要把各個欄位的釋義寫到資料庫中,該專案已經上線很長時間了,資料庫中的欄位沒有上千也有上百個,要是一個專案一個專案開啟然後再去找對應欄位檢視什麼意思,估計要到明年過年了。由於專案中使用EntityFramework,本身這個專案只有手動設定欄

CCS模擬如何CCS模擬時memory的資料以Hex、Integer、 Long 、Float、 Addressable Unit型別儲存到PC

2013-12-04 19:07:05 將在CCS中模擬的資料匯入電腦上時,可以選擇不同的資料型別,以便分析,具體方法如下: 在CCS選單中,選擇File—>Data—>Save,彈出以下視窗:                        

面經面試官問我:資料庫事務的隔離級別有哪些?各自有什麼特點?然而。。。

## 寫在前面 > 上週,一名讀者出去面試,面試官問了他有關於資料庫中事務的隔離級別的問題。然而他回答的比面試官想要的還要6。。。 > > 關注 **冰河技術** 微信公眾號,檢視更多 **面經** 與 超硬核 **專題** 技術文章。 ## 事務隔離級別 其實,面試官問的這個問題相對

utils指定的mysql資料庫的表生成java實體

開發的過程中需要將資料庫中的database中的tables和java中的物件一一對應,如果自己寫很麻煩,藉助小程式可以快速生成 mysql驅動包推薦 5.1.38 版本,用6以上版本有點問題。 自己開發的ORM框架:karma-orm,只是一

HLSDK系列服務端實體 edict_t 和 控制類

武器 .cpp 成員 常用 blog 生成 指針 但是 dll 我們來了解一下引擎是怎麽管理實體的吧!我們這裏就說說服務端的實體(edict_t) 服務端用 edict_t 這個結構體來保存一個實體,可以說一個 edict_t 就是一個 服務端實體,下文簡稱實體。 我們在

經驗分享如何一個PDF檔案拆分成多個檔案

從事於辦公的夥伴每天都需要處理到各式各樣的辦公檔案,PDF格式的檔案就是其中的一種,有時候遇到一份PDF檔案頁面比較多,處理起來很麻煩的話我們該用什麼樣的方法呢?在這裡可以將一個PDF檔案拆分成多個檔案,這樣子就方便了很多。下面就將這種方法分享給大家!以供大家參考。   &n

五味雜陳白晝成為黑夜

在漫長的人生中,總有一些歌,屬於特定的時刻。 丁可的《 Beautiful Life 》一定是屬於現在。 "  You see, birds in the sky   Flying so high   Got everywhere to go   You find, faces w

解決方案無法grub-efi-amd64-signed軟體包安裝到/target/安裝Ubuntu

簡述 很神祕,之前安裝雙系統的時候都是正常的。 但是這次居然失敗了。而且這個問題也很奇怪。 文章目錄 簡述 電腦配置 解決GRUB2安裝失敗的問題 正確的操作是 提要 開啟命令列

Share Code讓電腦說我愛你

讓電腦說我愛你 資源 原始碼&視訊 準備 Macbook或帶有AppleScript指令碼編輯器的裝置 開始 開啟指令碼編輯器 普通話 輸入程式碼 say "我愛你" using "Ting-Ti

Share CodeLAMP配置過程

原文連結 配置LAMP有兩種方法 單獨下載每個檔案,安裝 使用整合包 單獨下載每個檔案,安裝 安裝apache2 >apt-get install apache2 檢視apache2是否安裝成功 >apache2 -v

Share Code如何在Ubuntu 14.04 LTS上設定Apache虛擬主機

## 原文 & 視訊:https://zhaoshuquan.com/posts/8 ## 準備 安裝Apache,具體安裝過程可以參考這篇文章https://zhaoshuquan.com/posts/4 ## 第一步 - 建立目錄 第一步是建立一個目錄結構,該結構將儲存為訪問

VS Code"The 'clang-format' command is not available. Please check your clang-format."報錯

文章目錄 "The 'clang-format' command is not available......"報錯 說明 一、安裝外掛‘clang-format’ 二、解決方案 三、參考連結

Highcharts教程如何一個圖表拆分成圖表網格(上)

下載Highcharts最新版本 有時,當圖表具有高密度的資料點(例如具有多個系列的折線圖)時,視覺化可能最終變得混亂並且可能模糊不清。 通過一些仔細的規劃,可以使用多種方法避免資料密度問題。我將在這裡討論的一種方法是小資料或網格圖。此解決方案將資料系列分成單獨的圖表,這些圖表以網格排列,具有相同的

C/C++實現一個整數反轉

輸入一個整數並把整數所有數字倒序輸出 #include #include int reverseInt( int num ){ int result = 0; // 將整數倒序 for (

學習方法如何書上的知識學得更深?

其實答案早已在馬克思主義哲學原理的認識論中呈現(即使學過了這個原理,但是不懂得像這樣用來分析遇到的問題也是白搭,也是停留在書本,不夠深入)。   實踐與認識的辯證關係是:實踐決定認識,(認識可以反作用於實踐) ①實踐是認識的來源 ②實踐是認識發展的動力(這不就是是認識進行了進一步深化嗎?) ③實踐是認

已解決C#DLL嵌入到exe當中

System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)         {             string dllName = args.Name.Contains(",

知識圖譜知識圖譜實體連結無監督學習框架

雷鋒網 AI 科技評論按:阿里巴巴有 11 篇論文被 AAAI 2018錄用,分別來自機器智慧技

程式碼筆記Web-JavaScript-JavaScript註釋

一,效果圖。 二,程式碼。 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>javascript 註釋&l

課程10迴圈語句與註釋

while迴圈 #當某個條件成立後,持續迴圈#while 條件: #迴圈語句(迴圈體)'''def sumSum(star,end,step): i = star sum = 0 while i<=end: sum += i i += step return sumprint(sumSum(1,

iOS開發---- 快速大圖儲存到本地

       碰到一個問題:如何快速的批量儲存iphone相簿中的圖片(原始的大圖,解析度高)到本地? 儲存圖片到本地,首先得拿到這個圖片:alAsset.defaultRepresentation.fullResolutionImage.但是圖片太大了,大批量的儲存取這個