Ado.EF目前不支持添加在SQL Server中的說明,在類或屬性里添加說明/備注/Attribute,生成數據庫時,表或字段里不會有相應的說明/備注,但在實際的開發中是很有必要的。數據庫生成后,一般由DBA接手,但DBA可能並不了解每個字段的意義。在此,在本文中給出支持此功能的實現方法。
源碼下載:這里
原理
- 首先我們建立一個自定義Attribute類DBDescriptionAttribute,它包含一個屬性Description來保存設置在數據庫的說明文字
- 從DbContext中取得每個類對應的表名和列名
- 調用SQL Server的函數fn_listextendedproperty查表或字段是否存在“說明”屬性,SQL Server中的說明屬性對應的是“MS_Description"
select [value] from fn_listextendedproperty('MS_Description','schema','dbo','table',N'Students','column',null) select [value] from fn_listextendedproperty('MS_Description','schema','dbo','table',N'Students','column',null) where objname = N'Age'
4. 調用SQL Server存儲過程sp_addextendedproperty/sp_updateextendedproperty來添加或修改表/列的“說明”屬性
EXEC sp_addextendedproperty N'MS_Description', N'學生表', N'Schema', N'dbo', N'Table', N'Students' EXEC sp_updateextendedproperty N'MS_Description', N'年紀', N'Schema', N'dbo', N'Table', N'Students', N'Column', N'Age'
得到Table名
找到DbContext中包含的表,在DbContext中包含的所有實現DbSet<T>的屬性,得到相應的類型TableType,利用ObjectContext.CreateObjectSet<T>().ToTraceString()取相應執行的Sql語句,它是EF自動生成的,當它在創建Set時,會生成一個包含所有字段和表名的Sql語句,如:SELECT [Extent1].[Id] AS [Id], [Extent1].[Name] AS [Name], [Extent1].[Age] AS [Age] FROM [dbo].[Students] AS [Extent1] ,正則解析此句得到表名。
得到Column名
拿到表對應的類型后,輪循所有公共屬性,檢查是否有指定屬性DBDescriptionAttribute,如果有,再檢查是否有ColumnAttribute屬性設置的Name值,如果不為空,則取出備用,如果為空,默認列名即為Property.Name。
兩個方法過程如圖所示:
具體實現請看源碼。
執行點為Migrations\Configuration中的Seed方法(此方法在執行完遷移后調用)
internal sealed class Configuration : DbMigrationsConfiguration<Models.EFTestContext> { public Configuration() { AutomaticMigrationsEnabled = true; } protected override void Seed(Models.EFTestContext context) { var updater = new DBDescriptionUpdater<EFTestContext>(context); updater.UpdateDatabaseDescriptions(); } }
實現后在程序包管理控制台中執行:update-database –verbos –force,再到SSMS中檢查表/字段是否添加/修改成功。
另一解決方案:
直接把類或屬性的注釋取出來,作為在數據庫中的說明文字,可以在App_Data下添加一個嵌入的XML文件來保存這些注釋,將以上方法中的用反射來取說明文字改成從XML文件中取說明文字即可。