Roy's Blog
go on,go on

整合 ADO.NET Entity Framework 到應用程式中(转)

roydux,2010年1月25日


架構考量
ADO.NET Entity Framework 是連接應用程式和資料庫之間的介面層,可將原本相當耗工的資料存取與物件對應(O/R Mapping)部份簡化成只需要能夠應用 LINQ 或 Object Service 就可以順利存取資料庫,對資料庫的應用程式開發人員來說,是一個相當棒的技術,而且由於 O/R mapping 被做掉,讓開發資料層物件的開發人員可以省下很多工夫,有更多的時間,可以回去陪女友或老婆。

若是一個全新的應用程式,可以很順理成章的利用 Entity Framework 來加速應用程式的開發,不過若是要在已經存在的應用程式中套用 Entity Framework 的話,就要有所計畫與考量了。在多數的企業應用程式中,都會分成數個元件層次(Layered Components),與資料庫較有關的資料存取,都套用在資料存取層(DALs)或是資料存取元件(DACs)中,然後由 Business Components(企業邏輯元件)和資料存取層溝通以讀寫資料庫中的資料,然後把執行結果交給 Presentation 來顯示使用者介面。

在資料存取層中,可以分成幾種設計方法:

由程式碼負責資料存取:使用 ADO.NET 元件連接與存取資料庫,資料庫中只有資料表與檢視表。 
由程式碼和 DBMS 共同負責資料存取:使用 DBMS 中的功能(例如資料庫物件),併同 ADO.NET 存取資料庫中的資料。 
由 DBMS 負責資料存取:使用 DBMS 中的功能,設計一個存取介面,應用程式則用 ADO.NET 連接到 DBMS 中的存取介面以存取資料。 
在商業邏輯層中,要視資料存取層的設計法,來決定商業邏輯層的設計方法:

資料存取元件負責做 O/R Mapping:直接取用資料存取元件中的物件來讀寫資料。 
資料存取元件只回傳 DataRow/DataTable/DataSet:由商業邏輯層做 O/R Mapping,要花的工會比較多一點。 
針對不同的應用程式架構做考量,才能夠有效的整合 ADO.NET Entity Framework 到正確的位置,並且發揮最多的效率。

架構整合
我們在前面幾篇中所提到的技術,各有適用的層面:

技術 適用位置 說明 
Entity Client 資料存取 與 ADO.NET 物件相似,在初學 ADO.NET Entity Framework 時可以利用。 
Entity SQL 資料存取 DBA 或習慣使用 SQL 存取資料之開發人員可以利用。 
Object Service 資料存取
商業邏輯 支援 Entity SQL,適合於商業邏輯(程式碼)或資料存取層之用。 
LINQ to DataSet 商業邏輯 若資料存取層回傳 DataSet 或 DataTable 時,可改寫商業邏輯層,使用 LINQ 來查詢。 
LINQ to SQL 資料存取
商業邏輯 將資料存取層交給 DBMS,或者在資料存取層做 O/R Mapping,再用商業邏輯在讀寫資料存取層。 
LINQ to Entities 商業邏輯 在商業邏輯層中讀寫 Entity,由 Entity 來做為資料存取層。 

開發人員可以透過技術的選擇,來將 Entity Framework 整合到應用程式中,而不同的發展方式也會影響技術的選擇:

資料存取層中:

技術 套用技術 說明 
由程式碼負責資料存取 Entity SQL
Object Service 產生 Entity Data Model,然後用 Object Service 存取。 
由程式碼和 DBMS 共同負責資料存取 LINQ to Entities
Object Service
Entity SQL 產生 Entity Data Model,然後用 Object Service 或 LINQ to Entities 存取。 
由 DBMS 負責資料存取 LINQ to SQL 直接連接與存取 DBMS。 

商業邏輯層:

技術 套用技術 說明 
資料存取元件負責做 O/R Mapping Object Service
LINQ to Entities
LINQ to SQL 直接取用資料存取元件中的物件來讀寫資料。 
資料存取元件只回傳 DataTable/DataSet LINQ to DataSet 直接利用 LINQ 存取來自資料存取元件的 DataTable/DataSet。 

整合實例 A:將 DAL(資料存取層)以 Entity Model 取代
例如,一般在資料存取層中可能會寫像這樣的程式碼(備註,以下的整合實例都採用相同的程式碼):


public static DataTable GetProductList(string Category)
{
    SqlConnection conn = new SqlConnection(connectionString);
    SqlCommand cmd = new SqlCommand(
“SELECT * FROM ProductInfo WHERE CategoryID = @catID”, conn);
    SqlDataAdapter adapter = new SqlDataAdapter (cmd);
    DataTable table = new DataTable()

    adapter.Fill(table);

    conn = null;
    cmd = null;
    adapter = null;
    return table;
}


<>而商業邏輯層可能會寫這樣的程式碼(O/R mapping 做在商業邏輯層的建構子函式): 

DataTable table = DataService.GetProductList(categoryID);

List<ProductInfo> productList = new List<ProductInfo>();

foreach (DataRow row in table.Rows)
     productList.Add(row[“ProductID”].ToString(), row[“Caption”].ToString(), …);


在套用 Entity Framework 後,若是直接使用資料庫建立 Entity 的話,DAL 可以直接以 Entity Model 取代,而商業邏輯層可以改寫為:


var query = from p in db.ProductInfo
              where p.CategoryID == categoryID
              select p;

// output product list to List<T> collection.
List<ProductInfo> productList = query.ToList();

// access objects.
foreach (var r in query)
     productList.Add(p.ProductID, p.Caption, …);


直接套用 Entity Model 的方式可以省下開發與修改DAL的時間,非常適合應用在小型或原本沒有DAL的應用程式所取用,這個方式稱為直接對應模型(Direct Mapping Model)但若原本就有 DAL,這樣是否會花太多時間,這個是需要評估的。

整合實例 B:改寫 BLL(商業邏輯層),以存取來自 DAL 的資料物件。
若以改寫 BLL 程式碼的方式來套用 Entity Framework,則可以利用 LINQ to DataSet 來實作:


DataTable table = ProductInfo.GetProductList(categoryID);
var query = from p in table.AsEnumerate()
              where p.CategoryID == categoryID
              select p;

// output product list to List<T> collection.
List<ProductInfo> productList = query.ToList();
// access objects.
foreach (ProductInfo product in productList)
     productList.Add(product.Field<string>(“ProductID”), 
product.Field<string>( “Caption”), …);


改寫 BLL 的方式對於重構 BLL 有正面效果,也可以省去改寫 DAL 的時間,對於現有應用程式的整合有較正面且快速的幫助,而且只要關注 DAL 回傳的資料物件,不必煩惱要存取何種類型的資料。

整合實例 C:利用自訂的 Mapping 方式來產生 Entity
像是 Entity Framework 可以利用 CSDL 來建構物件模型;用 SSDL 對應實體儲存;並用 MSL 來結合兩者,這代表可以在 CSDL 固定的情況下,改寫 SSDL 對應方法來改變實體儲存的位置(例如 SQL Server, Access, MySQL, Oracle 等),或者是對應可能原始儲存和物件模型完全不同的結構時,透過 MSL 就可以結合 CSDL 與 SSDL,讓應用程式可以順利的讀取到資料。

這種方式稱為彈性對應(Flexible Mapping),彈性對應的模式可以讓物件模型和儲存模型得以切開,並且只要透過 MSL 就可以將兩者整合,這樣的設計方法可降低程式碼與資料的藕合性,而且應用程式又可以透過像 Object Service 或 LINQ to Entities 等方式來撰寫資料存取程式碼,不必在意儲存端要如何改變,即可有效的分離資料和邏輯兩部份(資料多為 DBA 的工作)。

例如,應用程式有一個物件模型,宣告為 CSDL 如下所示:


<EntityContainer Name="ModelContainer" >
<EntitySet Name="ProductInfoSet" EntityType="DataModel.ProductInfo" />
</EntityContainer>
<EntityType Name="ProductInfo" >
<Key >
<PropertyRef Name="ProductID" />
</Key>
<Property Name="ProductID" Type="Guid" Nullable="false" />
<Property Name="Caption" Type="String" Nullable="true" 
MaxLength="2147483647" Unicode="true" FixedLength="false" />
<Property Name="Description" Type="String" Nullable="true" 
MaxLength="2147483647" Unicode="true" FixedLength="false" />
</EntityType>


開發人員可以寫這樣的 Storage Schema,以將資料儲存在資料表中:


<EntityType Name="ProductInfoType">
<Property Name="ProductID" Type="String" Nullable="false" />
<Property Name="Name" Type="String" Nullable="false" />
</EntityType>
	  
<EntityContainer Name="TargetContainer">
<EntitySet Name="ProductInfoQuery" EntityType="ProductInfoType" />
</EntityContainer>


或者,若你想要以 SQL 查詢結果做為資料對應的來源,可以改成這樣:


<EntityContainer Name="TargetContainer">
<EntitySet Name="ProductInfoQuery" EntityType="DirectQueryTable">
	  <DefiningQuery>
		  SELECT ProductID, Name FROM Products
	  </DefiningQuery>
    </EntitySet>
</EntityContainer>


如此,就算資料來源或結構不同,程式端的物件模型也不會改變,一樣可以保持原程式不變動。

結語
筆者在本篇系列文章中,說明了 ADO.NET Entity Framework 的發展方法以及技術,以及整合的考量與方法,由於 ADO.NET Entity Framework 仍處於 Beta 2 狀態,未來若有更新功能的變動,筆者會以專文來介紹,希望讀者能夠在這個系列文章中獲得想要知道的資訊,若有問題,也可以在 MSDN 論壇的 ADO.NET and LINQ 討論區發問,預祝大家學習順利。



原文地址:http://www.microsoft.com/taiwan/msdn/columns/jhu_ming_jhong/ADO.NET_Entity_Framework_Integration_with_exist_applications.htm

Tags: ADO.NET Entity Framework  

分类: .NET | 评论:0 | 浏览:

相关文章:

发表评论