[翻譯]ORM in .NET 3.5
ORM in .NET 3.5
原文鏈接:http://dotnetslackers.com/articles/net/ORMInNET35.aspx
IntroductionORM,對象-關系映射,在現代面向對象編程語言中,其中實現起來比較棘手的事。它包括摒棄傳統的數據存儲機制:這里沒有(或很少)專門的、預編譯的代碼,涉及讀(寫)對象從(到)數據庫或其它后備存儲中。作為替代,涉及訪問后備存儲的邏輯在運行時被決定,通過運用一系列反射和特性機制修飾正在考慮的業務對象。許多已經建立的工程和框架試圖提出這個觀念并取得了多方面的成功。這篇文章覆蓋了:概括介紹ORM理念,一種.NET3.5攜帶的途徑,及其和其他框架的比較。
In the beginning...
在.NET3.5之前,當你需要把你的業務對象從數據庫讀取或寫入時,你有以下幾個選擇:
1. 自己動手 – 這意味著你不需要任何框架,不需要自動生成任何代碼。數據庫結構和.NET類都是手工建立的,數據訪問層也是如此。雖然這將會提供最終的執行,但是當對象或數據庫結構改變時,它將是乏味的(包括復制大量重復代碼),易出錯的,難以維護的。
2. 自動生成類和數據訪問層 – 這就是自動生成工具CodeSmith和MyGeneration到來的緣由:你在你的數據庫中指明它們,它將自動生成.NET類和數據訪問層。看看第一條選擇,這不是真正的ORM:你仍然有預編譯代碼負責訪問數據庫用來讀取或寫入對象的數據。不過,它的自動生成代碼機制在這方面做出了正確的一步,排除了當創建類和數據訪問層時易出錯的人為因素。
3. 運用真正的ORM框架 – 在先前的.NET框架版本中,這里有一些知名的ORM框架可獲取,包括NHibernate和Gentle.NET。就如事先提到的,ORM移除了專注于數據存儲的代碼和在運行時檢查一個對象來決定從數據庫讀取或寫入這個對象需要做哪些工作。特性用來修飾類和類的屬性,用以給出標識類和數據庫的映射。一個操作的真實SQL是基于這些特性動態生成的。經常有一個代碼自動生成組件在這些框架中用來從數據庫結構中生成業務對象類,但是關注于數據訪問的代碼沒有生成。
Major Malfunctions(缺點) with ORM所有這些動態的,運行時的SQL生成機制聽起來不錯,是么?并非如此:ORM有一些嚴重的缺點。第一個就是性能問題,因為在任何時候你把反射引入并開始動態生成SQL,你會遭遇減速。ORM永遠不會和自己手動處理一樣快:沒有替代品可以替代“手擰”存儲過程和預編譯所有數據訪問邏輯。另一個缺點是ORM對極度復雜的數據庫處理的不好。當設計很多約束和關系跨越多個表的復雜數據庫時,這經常有必要包括中間表去把各種實體關聯起來,這從RDBMS的立場看似乎不錯,但是在一個面向對象環境中看起來有點牽強。這也將導致難以理解自動生成的類。緊記,RDBMS和面向對象環境是根本不同的,它們各自擁有一套設計和性能考量。在一個環境中動作良好并不意味在另一個環境中亦如此。話雖如此,ORM以可維護、干凈的、易懂的代碼的方式提供正確的使用總是比較牽強的。
LINQ, DataContexts, and general ORM in .NET 3.5
目前為止,你對ORM已經有了整體的了解和它潛在的陷阱,讓我們探討一下Microsoft在.NET3.5中是如何接近這個觀念的。它提出了一個不同的途徑去挑戰ORM,它并不把焦點集中在對象模型、關系模型,它提供給我們一套全新的思路去訪問和查詢數據,這并不局限于關系數據。通過這個途徑,.NET3.5的ORM能力發展成了這個新的數據訪問架構,幾乎如同副作用一般,取代了原來的焦點。他們是怎樣做到的?LINQ。它代表集成查詢語言,Microsoft想把它變成在.NET框架中篩選數據的途徑。它的結構與我們平時寫SQL語句很類似,它非常簡單,并且擁有對強類型面向對象語言強有力的SQL查詢語法。實際的反對者,然而,是它不僅僅局限于關系數據:只要實現了IEnumerable和IQueryable接口,就能使用LINQ。這里有一個例子,你可以從中知道它的能力:
這只是一個簡單的從elements中查詢包含字母”n”的普通字符串例表實例。然而在之前你不得不命令式地完成這項功能,也就是你將不得不寫代碼迭代集合來驅動查詢,現在你可以直接地完成相同的功能。基本上,你陳述你要做什么來替代如何去做。當用這種語法,這種途徑固有地不太會出錯。它同樣也支持提及的智能感知,所以當你從事于LINQ編程時,你一點也不會在Visual Studio中損失輕松使用的特征。
那么,我們來看看LINQ是如何適合ORM的。第一,這里有一個代碼生成組件:LINQ并沒有避開它由于你不得不定義映射數據庫中的關系數據為類似于面向對象世界的類。為了做到這一點,Microsoft提供一個叫做SQLMetal的工具。為了使用它,僅僅打開Visual Studio命令行提示(Start->Programs->Visual Studio 9.0->Visual Studio Tools->Visual Studio Codename Orcas Command Prompt),然后打上sqlmetal來看看它的選項。它非常簡單:你所需要做的是指明它的數據庫,告訴代碼文件的名稱和(或)你想要生成的DBML文件。我創建了一個簡單的名為LinqTest的數據庫,它包含兩張表:Person和PersonAddress。PersonAddress有一名為personId的列,它是一個外部鍵,用來關聯Person表中相匹配的列。所以,我運用如下命令產生ORM類:
從這個過程得到的代碼結果中包含兩套類:DataContext類和一系列與數據庫中表相符的對象類。對象類非常簡單:它們反映出數據庫中的表,其中的屬性代表每個列。每個類和其屬性都被特性修飾,來描述和數據庫之間的映射,這和其他ORM框架類似。一個很好的提高是我并沒有在任何地方發現,除非每個對象類自動執行INotifyPropertyChanging和INotifyPropertyChanged,這意味著它們暴露了當一個屬性的值改變時允許外界類去響應的事件。為了促進這一點,要點是每個屬性包裝到OnPropertyChanging()和OnPropertyChnaged回調方法,依次觸發事件處理函數,如果它們設置了。另一個漂亮的特征是這樣一個事實,所有由SQLMetal產生的類都是部分類,它們僅僅實現必要的核心功能。這意味著你可以通過分離代碼文件自由的添加類功能,不需要更新自動生成的輸出。DataContext類提供鏈接到包含將用于移植到對象類的數據的后備存儲的服務(在這個例子里是數據庫)。你通過一個連接字符串或一個初始化了的數據連接對象來得到它的構造器,依次,它暴露一系列泛型屬性Table<>,其中每個都代表數據庫中的一張表。這些Table<>屬性是真正給予LINQ力量的:Table<>類是完全支持LINQ的,它負責于扮演LINQ與數據庫間的接口,將LINQ語法翻譯成必要的SQL語句,從而從數據庫中檢索你的數據。同樣地對于先前的例子,讓我們來看看另一個使用Table<>屬性的LINQ查詢:
所有這些講述了ORM實現是如何地困難,鑒于在.NET3.5中其他的看起來有點虎頭蛇尾:它對于有SQL經驗的非常容易懂,它完全集成于語言及開發環境,而且它令人驚訝的快。想添加一個新Person信息到數據庫?沒問題:
只要你調用必要的Table<>屬性的Add()方法,做完這步之后,調用DataContext類的SubmitChanges()方法。
Wrapping it up 總結
我希望這篇文章能給你一些好的建議對于在.NET3.5中處理ORM。這并不是解決所有挑戰數據訪問的銀彈,但就如任何一個優秀的程序員所知,這從來就沒有。當數據庫結構很復雜并且性能至關重要時,這里就沒有辦法替代手工寫代碼,調整.NET數據訪問代碼和SQL邏輯。但是,至于明確的結構和.NET中一般的數據過濾,LINQ表現為一種新的,詭秘的ORM實現。
posted on 2008-05-03 00:37 nicholas.sun 閱讀(3949) 評論(15) 收藏 舉報
浙公網安備 33010602011771號