【繁星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>
/// <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>(
[NotNull] this PropertyBuilder<TProperty> propertyBuilder,8
[CanBeNull] string comment)9
{10
return (PropertyBuilder<TProperty>) propertyBuilder.HasComment(comment);11
}也就是說我們要獲取到實體物件的註釋xml,然後讀取對應的欄位註釋,自動呼叫改方法即可。需要解決的問題大概有以下幾點。
- 如何獲取當前配置的欄位;
- 載入Xml,並根據欄位獲取對應的註釋;
- 如何將列舉的各項資訊都放入註釋中;
二、實現方法
1.如何獲取當前配置的欄位
在獲取xml的註釋中,需要的資訊有實體對應的型別以及對應的欄位。而包含這兩種型別的方法只有Property這個方法,該方法的出入參如下: 2 1public 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
else7
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 SummaryXmlCacheProvider5
{6
#region TClass7 8
/// <summary>9
/// 根據型別初始化該類所在程式集的xml10
/// </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
/// 根據型別獲取該類所在程式集的xml20
/// </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的key31
/// </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
#endregion40 41
#region TProperty42 43
/// <summary>44
/// 根據型別以及欄位初始化該類所在程式集的xml45
/// </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
/// 根據型別以及欄位獲取該類所在程式集的xml57
/// </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的key71
/// </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
#endregion87 88
#region TEnum89 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
#endregion123 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
/// 根據程式集初始化xml160
/// </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 Code】LAMP配置過程
原文連結 配置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.但是圖片太大了,大批量的儲存取這個