使用數(shù)據(jù)庫元數(shù)據(jù)為Entity Framwork實體生成注釋 眾所周知Entity Framwork自動生成的實體上沒有注釋。 img1 沒錯,我使用的是Entity Framwork的各種應(yīng)用模式中的數(shù)據(jù)庫先行模式。本文不討論Entity Framwork的哪種應(yīng)用模式更好的問題而是討論Entity Framwork
使用數(shù)據(jù)庫元數(shù)據(jù)為Entity Framwork實體生成注釋
眾所周知Entity Framwork自動生成的實體上沒有注釋。
img1
沒錯,我使用的是Entity Framwork的各種應(yīng)用模式中的數(shù)據(jù)庫先行模式。本文不討論Entity Framwork的哪種應(yīng)用模式更好的問題而是討論Entity Framwork提供的T4模板沒有生成實體注釋的問題。
通常架構(gòu)數(shù)據(jù)庫的時候會書寫描述架構(gòu)的元數(shù)據(jù)。如
img2
SqlServer把這些元數(shù)據(jù)存儲在哪里我不關(guān)心。但是從下圖可以發(fā)現(xiàn)貌似這種元數(shù)據(jù)是個鍵值對結(jié)構(gòu)。并且該類元數(shù)據(jù)被稱作Extended Properties
img3
通常數(shù)據(jù)庫會以數(shù)據(jù)庫愛好的方式提供操作數(shù)據(jù)的接口。操作這里的Extended Properties類別的元數(shù)據(jù)的接口是什么呢?是下面一個系統(tǒng)元數(shù)據(jù)函數(shù)和三個系統(tǒng)存儲過程:
img4
img5
img6
img7
這四個接口剛好完成我們所需要的對Extended Properties類別元數(shù)據(jù)的CRUD操作??上?,Entity Framwork的實體數(shù)據(jù)模型中并不包含這類屬性。雖然這類元數(shù)據(jù)與ORM無關(guān)但是它們對我們的代碼有利,如果能把這類元數(shù)據(jù)以注釋的形式加到實體類代碼上的話。
為了確認(rèn)Entity Framwork的實體數(shù)據(jù)模型上不包含這類元數(shù)據(jù),現(xiàn)在然我們以數(shù)據(jù)庫優(yōu)先的方式創(chuàng)建一個Entity Framwork項目,隨便找一個數(shù)據(jù)庫建好了后從數(shù)據(jù)庫更新元數(shù)據(jù)
img8
在點擊“Update Model From Database”之前開啟SqlServer Profiler程序
img9
通過監(jiān)視Entity Framwork更新元數(shù)據(jù)的sql代碼可以發(fā)現(xiàn)Entity Framwork并沒有查詢Extended Properties類別的元數(shù)據(jù)。上面說了這類元數(shù)據(jù)與ORM這件事情無關(guān),所以干正經(jīng)事的Entity Framwork根本不需要查詢這類元數(shù)據(jù)。但是我們想要利用數(shù)據(jù)庫中的Extended Properties元數(shù)據(jù)為實體代碼自動添加注釋,這件事對于我們來說是正經(jīng)事。想要利用實體數(shù)據(jù)模型上的元數(shù)據(jù)為實體代碼添加注釋的道路是難以走通了因為Ef都根本沒去查這類元數(shù)據(jù)。
那么,我們自建模型。通過監(jiān)視Entity Framwrok從數(shù)據(jù)庫更新元數(shù)據(jù)的Sql代碼我們領(lǐng)會到了SqlServer元數(shù)據(jù)數(shù)據(jù)訪問方面的知識。研究發(fā)現(xiàn)為生成實體數(shù)據(jù)模型元數(shù)據(jù)Entity Framwork查詢下如下結(jié)構(gòu)的四種數(shù)據(jù):
img10
上圖四種元數(shù)據(jù)分別對應(yīng)SqlServer的表、視圖、表列和視圖列。當(dāng)然這四類元數(shù)據(jù)現(xiàn)在表現(xiàn)為四張數(shù)據(jù)庫視圖這是經(jīng)過我封裝好了的。我們將這四張視圖作為提供元數(shù)據(jù)的“接口”。沒錯就是“接口”,誰規(guī)定過接口必須是C#中的interface關(guān)鍵字定義的結(jié)構(gòu)?接口是契約,這四張視圖就是我們的數(shù)據(jù)庫契約,現(xiàn)在我建的每個數(shù)據(jù)庫都實現(xiàn)了這個接口,它們都具有這四張視圖。這四張視圖是通過參考Entity Framwork獲取元數(shù)據(jù)的Sql語句建立的。這些Sql查詢太過復(fù)雜,尤其查詢表列和視圖列的元數(shù)據(jù)的查詢語句復(fù)雜的讓人難以入眼,下面只貼一個表視圖吧:
img11
有了上面四張視圖,再加上三個系統(tǒng)存儲過程sys.sp_addextendedproperty、sys.sp_updateextendedproperty、sys.sp_dropextendedproperty和一個系統(tǒng)元數(shù)據(jù)函數(shù)::fn_Listentendedproperty,如果這些知識都是我們熟悉的或者留意過的則大部分人可以在頭腦中有一個大致的解決方案了。但作為善終,本文還得繼續(xù)。廢話少說,下面開始架構(gòu)和編碼。
討論到現(xiàn)在發(fā)現(xiàn)一直都是在圍繞著數(shù)據(jù)庫說事,可見數(shù)據(jù)庫這個概念很重要,所以我想把它抽象一下先,建個Db類:
img12
Db類很簡單基本沒有什么可說的,唯有它的GetConnection方法值得一說,我們將上面的類圖換個視角看一看:
img13
Db類的GetConnection方法構(gòu)建數(shù)據(jù)庫連接的任務(wù)是通過委托ADO.NET的DbProviderFactory類型的對象完成的,而dbProviderFactory作為DbProviderFactory類型的實例是通過ADO.NET的DbProviderFactories.GetFactory(this.ProviderName)靜態(tài)方法傳入ProviderName字符串構(gòu)建的
img14
當(dāng)然除了Db類外,我們也需要為表、表列、視圖、視圖列類別的元數(shù)據(jù)建模,不過它們四個并沒有出彩的地方:
img15
還記得前文提到的數(shù)據(jù)庫上的那四個視圖接口么?上圖的這四個對象模型映射的就是數(shù)據(jù)庫中的那四個視圖(關(guān)系模型)。Db類型的對象不需要持久化嗎?當(dāng)然需要,它持久化到數(shù)據(jù)庫中的Database表:
img16
同樣Database表也沒有什么出彩的地方,前文有一張圖上提到數(shù)據(jù)庫連接“引導(dǎo)庫”,服務(wù)器,Database表所在的庫就是這個引導(dǎo)庫。
模型建好的,為了簡化問題,就把上面的Db模型、DbTable模型、DbView模型、DbTableColumn模型和DbViewColumn模型當(dāng)數(shù)據(jù)訪問模型?,F(xiàn)在基于這四個模型定義一套元數(shù)據(jù)訪問接口:
img17
目前來說有意義的是圖上紅色矩形圈住的幾個方法。這幾個方法就是用以實現(xiàn)對Extended Properties類別的數(shù)據(jù)庫元數(shù)據(jù)的增刪改操作的,它們都是通過調(diào)用一個很臭的私有方法實現(xiàn)的:
img18
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com