EntityFramework 元資料 設計分析

2021-09-23 21:33:31 字數 3865 閱讀 5670

由於之前已經嘗試使用過 ef codefirst ctp4,所以這次在ef4.1發布的第三天,在 oea 框架中已經支援使用它來實現資料訪問層。而且,我們準備逐漸把原有的較量級orm框架給替換掉,並且使用ef中的元資料系統來完全充當 oea 中的 orm 元資料,以便使用這些對映資訊來實現一些更多的操作。由於還沒有時間把整個 ef 的 msdn 拿下,所以暫時只是在網上看了一些相關的文章。而最近又正好在重構 oea 框架的元資料子系統,所以,這篇文章裡,我主要對 ef 的元資料進行乙個簡單的分析。

注意,以下的分析只代表我的個人觀點。

不了解 ef 元資料的朋友,我這裡給出一篇我覺得寫得蠻不錯的查詢文章:《.net - ado.net entity framework : querying metadata》,大家有興趣可以看看。這次,先給出我認為 ef 的質量分析,方便以後檢視,接下來的文章會進行乙個更詳細的分析:

可擴充套件性:

效能:api易用性:

模型基本概念

在整個ef的對映資訊中,分為 object model、conceptual model、storage model、object-to-conceptual model、conceptual-to-storage model 五大類。前三類是表明靜態結構資訊,後兩類表示靜態結構間的對映資訊。這五類元資料,全部都由乙個靈活度極強的元資料系統來描述。

object model 表示物件模型,該元資料說明了執行時物件的特徵,如:clr執行時類名、屬性名等。

conceptual model 表示邏輯模型,該模型與資料庫元關、與程式無關,用於描述邏輯上的「領域模型」或者「業務模型」。

storage model 則表示資料庫中的靜態資訊,如:表名、列名。

而這三類模型間有許多的共通之處,例如,都可以用乙個統一的概念來描述不同模型中的不同概念:用「實體型別」來描述物件中的類、資料庫中的表、概念模型中的領域實體;用屬性來統一描述類的屬性、表的字段、實體的屬性。所以 ef 使用乙個簡單的 entitytype 來描述實體型別、用 edmproperty 來描述實體屬性。

但是,它們之間必然存在差異。這就意味著,同樣的乙個 entitytype 型別,需要支援不同的屬性。

屬性擴充套件

針對以上問題,ef 給出了乙個可擴充套件屬性的設計:

metadataitem 作為所有元資料型別的基類,使用集合的方式來提供了類似於 dynamicobject 一樣的屬性擴充套件系統。每個子元資料型別都通過 metadataproperties 集合來定義/新增自己支援的屬性 metadataproperty,該類宣告以下:

例如,structuraltype 型別中強型別屬性 members 是成員的集合,

執行時檢視如下:

而繼續除錯到基類,會發現 metadataitem 中的 metadataproperties 屬性集合中有一項正好就是名字為 members,而值是恰好是剛才 5 個成員的集合:

所以,不用看原始碼,我們也可以大膽地猜測,在 structualtype 中,members 這個屬性的內部實現其實就是在基類的集合中註冊乙個新的 metadataproperty 項。

可以看出,這是乙個動態屬性註冊的機制,動態語言執行時中的 dynamicobject、wpf及wwf 中的 dependencyproperty,都有類似的設計思想在其中。

這樣的機制可以讓我們不斷擴充套件屬性;不需要轉換為子類就能以「非反射」的方式來對各個屬性進行控制;換來的卻是屬性系統的效能相對低下。

型別擴充套件

第二個較大的擴充套件點在於:元資料型別是可擴充套件的。

在之前給出鏈結的文章中,可以看出,系統已經給出缺省了許多元資料型別,它們都位於 system.data.metadata.edm 命名空間中,如下圖中給出了一些重要的型別:

當然,這並不是全部的元資料型別。細看前面截圖中,metadataitem 有乙個 builtintypekind 屬性,它的型別是乙個列舉,例舉了ef中目前所有支援的元資料型別,不同的子元資料型別重寫這個屬性來返回不同的值。這個設計非常類似於 linq 系統中 expression 的設計,它們都在最頂層的基類中列舉了所有的子類,以方便通過列舉的判斷來識別執行時的型別。但是它們又不盡相同:expression 是表示程式語言中的表示式,而這些表示式是固定的,我們不會也無法去對它進行擴充套件;但是 ef 中元資料卻是可以任意擴充套件的,這點可以從 builtintypekind 屬性的名字中看出,它表示的是「系統內建的型別」,當然,也可以從 metadataproperty 中的屬性 propertykind 列舉看出,它有兩個值:

extended 就表示這個屬性是「非內建」的。

有了這樣的設計,理論上,我們可以在任意 dll 中擴充套件 ef 的元資料型別。而把例項全部都加入 metadataitem 的集合中就可以了。

但是,這也帶來了不利的方面,例如,在進行查詢的時候,不能象一般的 api 一樣進行強型別的導航。換句話說,我拿到乙個 metadataitem 的集合,如果我不把它們轉換為子型別的話,無法進行強型別屬性的使用,而只能使用字串的匹配。所以,要對 ef 的元資料進行強型別查詢,首先要了解整個元資料的結構,然後借助 linq 中的 oftype方法來進行查詢。例如,我在上面截圖中,使用 oftype的方式來查詢給定型別中所有成員中的屬性列表。這也導致了效能比較差。

為什麼是這樣的設計?

作為乙個框架,不可避免地要進行框架的可擴充套件性進行設計,而且,這往往是非常重要的。而且我認為,在 ef 的設計中,可擴充套件性是是元資料模組的首要設計目標

這樣的靈活度要求,實出無賴:ef 作為乙個通用的 orm 框架,不但要同時描述物件模型、概念模型、儲存模型,同時還要考慮到各種資料庫的相容,還需要保證未來可能出來的各種資料庫、各種方法、各種儲存結構都能被元資料系統支援並加以描述。

這樣的結構,可以把任意的資訊都設計出對應的型別,然後放入元資料系統中。這裡,為什麼能說任意呢,因為設計本身可以說是和 xml 格式等價,而目前 xml 作為一種通用的資料格式,基本上可以描述所有的資料。(具體為什麼和 xml 格式等價,這裡不再展開。)

結尾

擴充套件性對於框架來說非常重要,這樣的乙個元資料系統設計,對於我來說,是十分有**力的。我曾幾次考慮是否把 oea 元資料系統設計成類似的結構。但是,最終還是沒有這樣做。原因在於,在進行系統/框架/架構設計時,各種質量屬性都需要進行權衡,不可一味地追求某乙個屬性,而是應該找到適度的設計。這是一句老話,但是往往做起來很難。

程式設計是一門藝術,而權衡則是一輩子都要玩的藝術。

Entity Framework 架構簡介

當微軟的wcf 大行其道,通用資料訪問模型entity framework卻稍遜一籌,有很多需要完善和進步的地方,本文對entity framework 架構做一下簡介。實體框架 entitry framework 以下簡稱ef 看起來像乙個有趣的技術,更強大,比linq to sql 更先進。這兩...

entity framework 批量刪除

以前用sql寫批量刪除的時候,感覺挺利索的,簡潔地寫了 public bool delectusersuggest string addsql 然後在頁面層直接呼叫 現在用entity framework,感覺有點麻煩不能直接delete,還要先把資料查出來,以下是主要 1 先查出實體 region...

Entity Framework 動態查詢

不想多說什麼直接說 region 搜尋並分頁 ljy 傳入搜尋條件,當前頁碼,每頁的顯示的條數,資料的總數 輸出引數 三個引數,返回 商實體 搜尋條件 當前頁碼 每頁的顯示的條數 資料的總數 public iqueryable endregion 在頁面呼叫時如果通過時間來查詢,請記住一定要這樣寫 ...