比較NHibernate和實體框架
葡萄牙的一位開發者 Ricardo Peres 最近發布了一篇文章,以看起來無偏見的形式對領先的兩種 .NET ORM:NHibernate 和實體框架進行了比較。 我們建議考慮使用這兩種框架的人都應該讀下他的文章,NHibernate 和實體框架之間的區別,另外還將指出一些關鍵的區別。
從架構上看,NHibernate 基于 Java 的 Hibernate ORM。 Ricardo 寫道:
在 NHibernate 中,工作單元和配置項以及模型實例都相互獨立。 你首先會創建 Configuration 對象,在其中你會指定所有 NHibernate 設置,像要使用的數據庫和語言、批處理的大小、映射關系等等,然后你會依此構建 ISessionFactory。 ISessionFactory 會持有與特定數據庫綁定的模型和元數據,以及來自于 Configuration 對象的設定,并且,一般每個進程中只有一個實例。 最終,你會基于 ISessionFactory 創建 ISession 的示例,它是工作單元(Unit of Work)以及標識符地圖(Identity Map)的 NHibernate 表現形式。 這是一種輕量級的對象,它本質上會根據需要打開和關閉數據庫連接,并跟蹤與之相關的實體。 ISession 對象很容易創建和銷毀,因為所有的模型復雜性都存儲在 ISessionFactory 和 Configuration 對象中。
評論者 Morten Mertner 說:“我永遠都不會使用 NHibernate。 盡管它擁有很棒的特性列表,但它并非一種能夠輕松使用的產品,而且 API 和設計中始終帶有遺傳自 Java 的味道(同樣,很多 Java API 都太企業化,并且架構過于龐大;結果會與你想要的大相徑庭)。”
實體框架遵循的是更加傳統的 .NET 設計,其中所有一切都封裝在單獨的 ObjectContext 或者 DbContext 中。 這讓使用對象更加簡單,但是缺點在于“類并沒有因此是輕量級的,因為它有與 NHibernate 類似的內容,并且一般不會看到這樣的例子:實例可以緩存在字段中。”
對于映射,NHibernate 和實體框架之間的關鍵區別在于,前者支持基于 XML 的映射文件,該文件可以獨立部署。 在理論上,這讓你可以針對不同的數據庫 schema 使用相同的對象模型,而不需要重新編譯應用程序。 但在實踐中很少這么使用。
在很多方面古老一些的 NHibernate 要優于實體框架。 Ricardo 提供了更多細節,并簡要地總結如下:
- 關聯: 都支持一對一、一對多、多對多,但是 NHibernate 還支持各種排序、未排序和索引的選項。 它甚至還有不變的(immutable)、索引的(indexed)列表。
- 緩存: NHibernate 提供了帶有大量實現的二級緩存。 實體框架沒有任何對此內建的支持,但是有些增加二級緩存的例子。
- ID 生成: NHibernate 提供了大概十二種策略,這取決于你如何計算。 實體框架只為 SQL Server 提供了主要的三種: 標識符列、GUID、和手動賦值。
- 事件: 實體框架只有兩種基于事件的擴展點: ObjectMaterialized 和 SavingChanges。 “NHibernate 擁有非常豐富的事件模型,暴露了超過 20 種事件,有些針對同步前執行(synchronous pre-execution),有些針對異步后執行(asynchronous post-execution)”。
- 級聯: “兩種框架都支持集合和關聯的級聯: 當實體被刪除的時候,相關的子實體也會被刪除。 NHibernate 還提供了一種特性,可以把子實體上的外鍵設置為 NULL,而不刪除它們。”
- 清理變更: NHibernate 提供了一種自動模式,其中在必要的時候會保存變更,像“如果有一種實體類型的臟實例,而查詢是針對這種實體類型執行”。 FlushMode.Auto 實際上是默認值,但偶爾會看到由于自動清除而導致性能問題。
也有一些領域中,實體框架會比 NHibernate 好,比方說:
- 跟蹤變更: 盡管兩種框架在工作單元級別默認都能夠跟蹤變化,而實體框架還提供了自我跟蹤實體(self-tracking entities)。
- 整合: 實體框架當然會與 Visual Studio 和各種 ASP.NET 以及 WCF 類庫有很好的綁定。
- 文檔: “這是另一種實體框架表現非常好的地方: NHibernate 缺少針對初學者的文檔,并且也沒有與其最新版本同步的最新 API 參考。”
- 查詢: Craig 寫到:“NHibernate 有更豐富的特性,但有一個領域除外,那就是對 Linq 的支持。 因為對于很多用戶來說,Linq 或者其它查詢語言都是 ORM 中最可見的部分,它會讓人對功能產生錯誤印象。”
還有某些領域,兩種框架都可以做出改進,像批處理功能。 當需要真正支持 SQL 的高級特性——像通用表表達式——的時候,兩種 ORM 框架都無法支持 SQL Alchemy。
我們應該發現兩個項目都很活躍,經常會有定期的改進。 所以,如果二者都能夠滿足你的最小需求,那么考慮就更多集中在程序庫的設計模式和哲學上,而不是在特性列表上。
查看英文原文:Comparing NHibernate and Entity Framework