程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 數據點: 設計實體數據模型

數據點: 設計實體數據模型

編輯:關於.NET

實體框架是為 ADO.NET 開發的一種激動人心的新技術。開發人員可以借助它使用邏輯模型(而不是物 理模型)查看數據,並提供了更高的靈活性。

實體框架的核心是實體數據模型 (EDM)。EDM 定義開發人員通過代碼進行交互的實體類型、關系和容 器。實體框架將這些元素映射到關系數據庫公開的存儲架構上。EDM 通過用於定義概念應用程序模型的 XML 向實體框架公開。概念模型可單獨定義,也可與用於定義實際存儲架構的 XML 以及用於定義兩者之 間映射的 XML 一起定義。盡管可以(有時也有必要)手動編輯 XML,但使用新的可視化實體數據模型設 計器工具來創建和修改實體模型和映射會更加容易。

在本月的專欄中,將討論如何使用新的可視 化 EDM 設計器工具來設計實體模型,以及如何修改用於定義模型和映射的基礎 XML。我將首先介紹在實 體框架(包括 LINQ)中進行交互的各個方面,然後討論 EDM 適合在何處使用。此外,還將演示如何使用 可視化設計器工具創建實體模型和關聯的映射。最後,將向您介紹可以幫助您修改和探索模型和映射的幾 個窗口。

在整個專欄中,我將解釋 EDM 的不同組件(例如 EntityType 和 Association)的作用 。本專欄中的示例演示了如何創建基本實體。請注意,本專欄中的所有示例均使用 Visual Studio® 2008 以及相應的 Entity Framework Beta 3(這些需要單獨安裝)。我使用的數據庫是含有 Beta 3 中 示例的經修改的 Northwind 示例數據庫。

理解 EDM

在探討如何創建和管理實體模型之前 ,首先介紹什麼是 EDM 以及它與實體框架的其他元素之間如何進行交互。實體框架由許多部分組成,包 括 EDM 規范及關聯的映射、與 EDM 交互的 API,以及幫助定義和管理實體模型和映射的工具。設計實體 模型之後,可以使用不同的 API 根據實體模型來編寫代碼,例如 EntityClient 提供程序或對象服務( 包括 LINQ to Entities)。

EntityClient 數據提供程序具有與傳統 ADO.NET 對象類似的模型, 因為它使用 EntityConnection 和 EntityCommand 對象返回 DbDataReader。EntityClient 提供程序的 命令是使用與 T-SQL 類似的實體 SQL 編寫的,它對實體模型中定義的實體以及通過對象服務具體化的對 象進行操作,而不是對數據庫對象進行操作。您可以通過實體 SQL 或 LINQ to Entities 使用對象服務 與 EDM 進行交互。通過對象服務,您可以利用概念模型的生成類,這些生成類提供了強類型化對象和持 久性等特性(參見圖 1)。

圖 1 實體框架概述

通過這些數據訪問技術,您可以與實體模型中定義的概念實體進行交互,而不是與物理存儲區(例如 關系數據庫)的對象進行交互。使用可視化設計器工具或手動編輯用於定義模型和映射的 XML,可以創建 數據模型及關聯的映射。圖 2 中顯示的實體框架為應用程序及其數據庫之間提供了關聯。EDM 用於通過 概念實體模型和實體框架、通過映射規范來描述業務實體,然後將其轉換為數據庫物理存儲區的表、視圖 、功能和過程。

圖 2 實體框架將應用程序連接到其數據庫

應用程序的實體模型是使用概念架構定義語言 (CSDL) 描述的。CSDL 是一種用於定義實體及實體之間 關聯的 XML 格式,開發人員通過 API(例如 LINQ to Entities)可與實體進行交互。實體框架還使用存 儲架構定義語言 (SSDL)(一種用於定義關系數據庫的存儲架構的 XML 格式)和映射架構語言 (MSL),來 轉換 CSDL 的實體映射到 SSDL 所描述的存儲架構的方式。

CSDL 是開發人員影響作用最大的地方 ,因為開發人員最常交互的實體就是用它定義的。圖 2 顯示了可以將一些實體直接映射到數據庫中的單 個表中,而其他實體可以映射到多個表中。此實體是由開發團隊根據業務模型來決定的。業務模型通常對 數據庫中多個物理表中存在的單個實體進行操作。從圖 2 還可以看出,實體可以映射到數據庫的視圖中 ,也可以獲取用於調用存儲過程的方法。實體還可以使用概念模型中的繼承從其他實體派生而來。以下是 使用 EDM 設計器工具設計實體模型的一些方法。

使用向導構建 EDM

若要創建實體模型,首先需要添加新的 ADO。項目的 NET Entity Data Model 文件(參見圖 3)。完成此操作後,實體數據模型向導將提示您是從數據庫中生成模型還是從空模 型開始構建。從現有數據庫表中生成模型是一種不錯的開始方法,只要有權訪問數據庫即可。某些開發方 法(例如域驅動的設計)提倡在設計數據庫之前設計實體域模型。如果您計劃采用此類方法,則可能需要 通過 EDM 可視化設計器創建一個空模型,然後創建您的實體。在我的示例中,開始時我使用 Northwind 數據庫構建了一個實體模型。

圖 3 向您的項目添加 EDM 文件

向導的下一屏幕提示您輸入數據庫連接信息。然後,向導會要求您選擇模型中要包含的數據庫對象。 在圖 4 中可以看出,我選擇了 Northwind 數據庫中的所有表和存儲過程(幫助繪制圖表的除外)。表最 初直接映射到實體,存儲過程可映射到生成容器上的方法。

圖 4 選擇數據庫對象

指定要在模型中包含的數據庫對象之後,EDM 向導會生成用於定義模型和映射的 .edmx 文件,並向實 體框架需要的項目添加相應的引用。.edmx 文件是一個 XML 文件,包含四個主要部分:關於設計器中概 念模型的可視化布局的信息、概念模型的 CSDL、映射層的 MSL 以及物理模型的 SSDL。上述所有信息均 包含在一個文件中。

.edmx 文件的設計器信息用於輔助 Visual Studio 在設計器中對實體模型進 行布局;此文件僅在設計時使用。CSDL、MSL 和 SSDL 在編譯時使用,用於生成表示 EDM 的類。

實體模型中的存儲過程

我已選擇向我創建的實體模型添加存儲過程,但僅將存儲過程添加到了 SSDL 定義。因為存儲過程可以與數據庫中的許多不同表或其他對象進行交互,所以實體框架不會將存儲 過程自動映射到 CSDL 中的任一特定實體。如果需要創建映射到存儲過程的方法,則可以通過在 .edmx 文件中編輯 XML 來完成。

為了創建用於返回給定類型實體的方法,首先要選擇一個存儲過程。在 本例中,我將添加一個名為 GetTenMostExpensiveProducts 的方法,該方法將執行 Ten Most Expensive Products 存儲過程,並作為 Products 對象返回結果。在 SSDL 將存儲過程描述為 Function 元素之後 ,下一步就是向 CSDL 中添加方法。通過將 FunctionImport 元素添加為 EntityContainer 元素的子元 素可以完成此過程:

<FunctionImport Name="GetTenMostExpensiveProducts"
 EntitySet="Products"
 ReturnType="Collection(Self.Products)">
</FunctionImport>

Name 屬性表示實體容器上方法的名稱。EntitySet 屬性表示 EntitySet,ReturnType 屬性指將要返回的 EntityType(在本例中是指 EntityTypes 的集合)。

在本示例中,Self 的引用是一個別名,指當前命名空間(即 NWModel)。請注意,在此處 NWModel 或 Self 均可使用。

如果該方法中需要參數,則可以通過包含 <Parameter> 標記 來添加參數。例如,如果還想在方法中添加存儲過程中的 CategoryId 參數,則可以在 FunctionImport 元素中包含以下 XML 元素,從而將該參數添加到該方法中:

<Parameter 

Name="CategoryId" Type="Int32" Mode="in"/>

但我的示 例中沒有參數,因此跳過了這一步。

這時,CSDL 定義了方法、方法返回的實體類型以及返回的實 體所屬的 EntitySet,而 SSDL 定義了存儲過程。現在,需要將 CSDL 映射到 SSDL,以使概念方法了解 要執行何種存儲過程。通過將以下 FunctionImportMapping 插入 MSL 的 EntityContainerMapping 部分 可完成此映射:

<FunctionImportMapping
 FunctionImportName="GetTenMostExpensiveProducts"
 FunctionName="NWModel.Store.Ten_Most_Expensive_Products"/>

此處, FunctionImportMapping 元素使用 FunctionName 屬性引用 SSDL 中 Function 元素的完全限定名稱。 FunctionImportName 屬性引用 CSDL 中 FunctionImport 元素的名稱。

EDM 中的窗口

設 計和構建 EDM 之後,可以使用各種窗口來檢查您創建的實體模型的狀態。當需要檢查對象是否可用於進 行開發時,“類視圖”窗口(參見圖 5,該窗口不是一個新窗口)十分有用。例如,它將顯示 NWEntities EntityContainer 類上的新 GetTenMostExpensiveProducts 方法,以及 NWModel 命名空間 包含的所有類。其中有一個用於表示 CSDL 中每個 EntityType 的類,還有一個用於主要 NWEntities 模 型的類。

Figure 5(圖 5) 類視圖中的 EDM

還有一些新窗口,通過這些窗口您可以查看實體模型及相關映射。這些窗口包括“Entity Data Model Designer”(實體數據模型設計器)、“Entity mapping Details”(實體映射詳細信息)窗口以及 “Entity Model Browser”(實體模型浏覽器)窗口。

“Entity Model Browser”(實體模型浏覽器)顯示了所有 CSDL 組件和 SSDL 組件。其中包括 CSDL 組件 EntityTypes、Associations、EntitySets、AssociationsSets 和 Function Imports 以及所有 SSDL 元素。

“Entity Model Designer”(實體模型設計器)中(參見圖 6)顯示了包含已生成的模型的布局。通 過此設計器可以查看實體模型並對其進行操作,實體模型表示以可視化布局顯示的所有概念模型的元素。 請注意,圖 6 中有一個 Product 實體,它表示 CSDL 中的 Product EntityType。每個 EntityType 均 包含一個屬性列表(標量和導航)。

圖 6 實體數據模型設計器

導航屬性用於在 CSDL 的關聯中進行導航。導航屬性成為其 EntityType 類上的公共屬性,用於引用 另一實體或與原始實體相關的一系列實體。例如,Product EntityType 具有名為 Categories 的導航屬 性,該屬性將引用特定 Product 實體實例的 Category 實體。Category EntityType 還具有名為 Products 的導航屬性。此屬性的作用是使您可以通過 Category 實體實例引用與其關聯的 Product 實體 。

設計器可用於添加、編輯或刪除實體類型、關聯、標量屬性和導航屬性。例如,您可以將所有 EntityTypes 的名稱更改為開發人員在命名實體時常用的單數形式。只需單擊 EntityType 的名稱並在其 中編輯名稱即可。也可以選擇 EntityType,並在“Properties”(屬性)窗口中更改其名稱。在這些示 例中,我將所有 EntityTypes 重命名為單數形式,這在圖 6 可以反映出來。完成更改後,我還修復了此 前修改的 XML,將存儲過程調用添加為 NWEntities EntityContainer 的一個方法。此步驟非常簡單,只 需更新引用 Product EntityType(與 Products 相對)的代碼即可,如下所示:

<FunctionImport Name="GetTenMostExpensiveProducts"
EntitySet="Products"
ReturnType="Collection(Self.Product)">
</FunctionImport>

下面是需要重點注意的問題。最好在開始修改數據模型之前命 名主要元素,例如 EntityType、EntityContainer 和 Association。這樣可以最大限度地減少需要手動 更改的次數,對於您已針對數據模型編寫的代碼而言,也可以最大限度地減少需要更改的代碼次數。如果 遇到問題,“Error List”(錯誤列表)窗口將顯示哪些元素在 XML 中的引用無效,為您提供幫助。

最後,當設計器顯示概念模型時,“Entity Mapping Details”(實體映射詳細信息)窗口將提供一 種查看和編輯 EDM 與數據存儲區之間映射 (MSL) 的方法。

派生實體

幫助您設計實體模型的工具也可以幫助您修改模型。對於面向對象的編程而言,一個關鍵點是要了解 繼承的概念。EDM 支持在 XML 中和以可視化方式在 EDM 設計器中創建和修改繼承的實體。

為演示設計繼承實體的任務,我將基於 Product EntityType 創建 DiscontinuedProduct EntityType 。Product EntityType 具有名為 Discontinued 的 Boolean 標量屬性,我將其用作在確定產品特定實例 類型時要計算的 Condition。使用“Entity Model Designer”(實體模型設計器)時,可以在設計器中 單擊右鍵,然後從彈出菜單中選擇“Add”(添加)|“Entity”(實體)。然後,我輸入 DiscontinuedProduct 作為新實體名稱,並選擇 Product 作為基本實體(參見圖 7)。

圖 7 創建繼承實體

在下一步中,需要使用 Condition 定義這些實體之間的區別因素,因此我在設計器中選擇了 Product EntityType,並轉至“Entity Mapping Details”(實體映射詳細信息)窗口。然後,在“Column Mappings”(列映射)中選擇 Discontinued 屬性,並刪除該映射。這將從 Product 和 DiscontinuedProduct EntityTypes 中刪除 Discontinued 屬性(創建 Condition 時,Condition 的可 用表達式必須尚未用作屬性)。接著,轉至“Entity Mapping Details”(實體映射詳細信息)窗口的“ Maps to Products”(映射到產品)部分,並添加 Condition of Discontinued = 0。然後選擇 DiscontinuedProduct EntityType,並添加 Condition of Discontinued = 1。

使用此技術創建派生實體確實特別方便。如果需要,除基類的屬性之外,您還可以向派生實體添加其 他屬性。在 .NET 代碼中創建 DiscontinuedProduct 的實例並保存之後,實體框架就會知道必須將數據 庫中 Discontinued 列的值設置為 0,這是因為其中存在 Conditions。

Conditions 是在 MSL 的 EntityTypeMapping 部分創建的,在檢索行時只需實施篩選器即可。保存數 據時,Conditions 用於根據派生類型確定寫入基礎數據庫列的值。

結束語

使用 Visual Studio 2008 中的設計工具和 XML 文件,您可以設計使用繼承、調用存儲過程和對業務 建模的實體數據模型,而不用直接針對您的關系數據庫架構編寫代碼。設計完成可靠的實體模型之後,通 過 API(例如對象服務)與其進行交互就非常簡單了;對數據模型的修改也不需要在數據庫中進行,因為 映射可以將概念模型與存儲模型隔離開來。如果您對此處介紹的有關實體框架的一些概念不太熟悉,強烈 建議您參閱我的實體框架概述,網址是:msdn.microsoft.com/msdnmag/issues/07/07/DataPoints。

請將您想向 John 詢問的問題和提出的意見發送至 [email protected][email protected].

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved