天天看點

NHibernate介紹

在今日的企業環境中,把面向對象的軟體和關系資料庫一起使用可能是相當麻煩和浪費時間的。NHibernate是一個面向.NET環境的對象/關系資料庫映射工具。對象/關系資料庫映射(object/relational mapping,ORM)這個術語表示一種技術,用來把對象模型表示的對象映射到基于SQL的關系模型資料結構中去。

NHibernate不僅僅管理.NET類到資料庫表的映射(包括.NET 資料類型到SQL資料類型的映射),還提供資料查詢和擷取資料的方法,可以大幅度減少開發時人工使用SQL和ADO.NET處理資料的時間。

NHibernate的目标主要是用于與資料持久化相關的程式設計任務,能夠使開發人員從原來枯燥的SQL語句的編寫中解放出來,解放出來的精力可以讓開發人員投入到業務邏輯的實作上。對于以資料為中心的程式,開發人員往往是在資料庫中使用存儲過程來實作商業邏輯,這種情況下NHibernate可能不是最好的解決方案,但對于那些基于.NET,并且能夠實作OO業務模型和商業邏輯的中間層應用,NHibernate是最有用的。NHibernate可以幫助使用者消除或者包裝那些針對特定廠商的SQL代碼,并且幫使用者把結果集從表格式的表示形式轉換成一系列的對象。

1.NHibernate體系結構NHibernate體系結構如圖1-51所示。它展現了NHibernate如何使用資料庫和配置檔案資料來為應用程式提供持久化服務(和持久化的對象)。

[img,11,11]file:///C:/Documents%20and%20Settings/FAST/My%20Documents/1_5%20企業開發架構NHibernate和Spring_Net%20-%20《ASP_NET%202_0+SQL%20SERVER熱門網絡應用開發詳解》%20-%20免費試讀%20-%20book_csdn_net.files/image004.jpg[/img]    SessionFactory(NHibernate.IsessionFactory):它是Session的工廠,是ConnectionProvider的客戶。可以持有一個可選的(第二級)資料緩存,可以在程序級别或叢集級别儲存的可以在事物中重用的資料。

[img,11,11]file:///C:/Documents%20and%20Settings/FAST/My%20Documents/1_5%20企業開發架構NHibernate和Spring_Net%20-%20《ASP_NET%202_0+SQL%20SERVER熱門網絡應用開發詳解》%20-%20免費試讀%20-%20book_csdn_net.files/image004.jpg[/img]    會話(NHibernate.ISession):單線程,生命期較短的對象,代表應用程式和持久化層之間的一次對話。封裝了一個ADO.NET連接配接,也是Transaction的工廠。儲存有必需的(第一級)持久化對象的緩存,用于周遊對象圖,或者通過辨別符查找對象。

[img,11,11]file:///C:/Documents%20and%20Settings/FAST/My%20Documents/1_5%20企業開發架構NHibernate和Spring_Net%20-%20《ASP_NET%202_0+SQL%20SERVER熱門網絡應用開發詳解》%20-%20免費試讀%20-%20book_csdn_net.files/image004.jpg[/img]    持久化對象(Persistent)及其集合(Collections):生命期較短的單線程的對象,包含了持久化狀态和商業功能。這些可能是普通的對象,唯一特别的是現在從屬于且僅從屬于一個Session。一旦Session被關閉,它們都将從Session中取消聯系,可以在任何程式層自由使用(比如,直接作為傳送到表現層的DTO,資料傳輸對象)。

[img,11,11]file:///C:/Documents%20and%20Settings/FAST/My%20Documents/1_5%20企業開發架構NHibernate和Spring_Net%20-%20《ASP_NET%202_0+SQL%20SERVER熱門網絡應用開發詳解》%20-%20免費試讀%20-%20book_csdn_net.files/image004.jpg[/img]    臨時對象(Transient Object)及其集合(Collection):目前沒有從屬于一個Session的持久化類的執行個體。這些可能是剛剛被程式執行個體化,還沒有來得及被持久化,或者是被一個已經關閉的Session執行個體化。

[img,11,11]file:///C:/Documents%20and%20Settings/FAST/My%20Documents/1_5%20企業開發架構NHibernate和Spring_Net%20-%20《ASP_NET%202_0+SQL%20SERVER熱門網絡應用開發詳解》%20-%20免費試讀%20-%20book_csdn_net.files/image004.jpg[/img]    事務Transaction (NHibernate.ITransaction):(可選)單線程,生命期較短的對象,應用程式用其來表示一批工作的原子操作,它是底層的ADO.NET事務的抽象。一個Session在某些情況下可能跨越多個Transaction事務。

[img,11,11]file:///C:/Documents%20and%20Settings/FAST/My%20Documents/1_5%20企業開發架構NHibernate和Spring_Net%20-%20《ASP_NET%202_0+SQL%20SERVER熱門網絡應用開發詳解》%20-%20免費試讀%20-%20book_csdn_net.files/image004.jpg[/img]    ConnectionProvider(NHibernate.Connection.ConnectionProvider):(可選)ADO.NET連接配接的工廠。從底層的IDbConnection抽象而來。對應用程式不可見,但可以被開發者擴充/實作。

[img,11,11]file:///C:/Documents%20and%20Settings/FAST/My%20Documents/1_5%20企業開發架構NHibernate和Spring_Net%20-%20《ASP_NET%202_0+SQL%20SERVER熱門網絡應用開發詳解》%20-%20免費試讀%20-%20book_csdn_net.files/image004.jpg[/img]    TransactionFactory(net.sf.hibernate.TransactionFactory):(可選)事務執行個體的工廠。對應用程式不可見,但可以被開發者擴充/實作。

2.持久化類持久化類是應用程式用來解決商業問題的類(比如,在電子交易程式中的Customer和Order)。持久化類是暫時存在的,執行個體會被持久性儲存于資料庫中。

如果這些類符合簡單的規則,NHibernate能夠工作得最好,這些規則就是Plain Old CLR Object(POCO,簡單傳統CLR對象)程式設計模型。

POCO簡單示例(用一個類描述一隻貓)如下:

#001    public class Cat

#002    {

#003       private long _id;                  // 辨別符

#004       private string _name;             // 名字

#005       private DateTime _birthdate;        // 出生日期

#006       private Cat _mate;                // 貓的配對

#007       private Set _kittens;                 // 貓仔

#008       private Color _color;               // 顔色

#009       private char _sex;              // 性别

#010       private float _weight;             // 體重

#011           public long Id              // 辨別符屬性

#012     { get { return _id; }

#013               set { _id = value; }

#014       public string Name              // 名字屬性

#015           { get { return _name; }

#016          set { _name = value; }}

#017       public DateTime Birthdate          // 出生日期屬性

#018           { get { return _birthdate; }

#019               set { _birthdate = value; }}

#020       public Cat Mate                 // 貓的配對屬性

#021           { get { return _mate; }

#022         set { _mate = value; }}

#023       public Set Kittens              // 貓仔屬性

#024           { get { return _kittens; }

#025               set { _kittens = value; }}

#026       public Color Color              // 顔色屬性

#027           { get { return _color; }

#028               set { _color = value; }}

#029       public char Sex                 // 性别屬性

#030           { get { return _sex; }

#031               set { _sex = value; }}

#032       public float Weight             // 體重屬性

#033           { get { return _weight; }

#034               set { _weight = value; }}

#035    }

有4條主要的規則如下。

[img,11,11]file:///C:/Documents%20and%20Settings/FAST/My%20Documents/1_5%20企業開發架構NHibernate和Spring_Net%20-%20《ASP_NET%202_0+SQL%20SERVER熱門網絡應用開發詳解》%20-%20免費試讀%20-%20book_csdn_net.files/image004.jpg[/img]    為持久化字段聲明通路器(getters和setters)。

[img,11,11]file:///C:/Documents%20and%20Settings/FAST/My%20Documents/1_5%20企業開發架構NHibernate和Spring_Net%20-%20《ASP_NET%202_0+SQL%20SERVER熱門網絡應用開發詳解》%20-%20免費試讀%20-%20book_csdn_net.files/image004.jpg[/img]    Cat為它的所有可持久化字段聲明了getters和setters通路器。用通路器來替代直接通路字段是個好習慣。也可以通過字段(field)來使用NHibernate。屬性不一定需要聲明為public的。NHibernate可以對default、protected、internal或private的屬性執行持久化。

[img,11,11]file:///C:/Documents%20and%20Settings/FAST/My%20Documents/1_5%20企業開發架構NHibernate和Spring_Net%20-%20《ASP_NET%202_0+SQL%20SERVER熱門網絡應用開發詳解》%20-%20免費試讀%20-%20book_csdn_net.files/image004.jpg[/img]    實作一個預設的構造方法(constructor):Cat有一個顯式的無參數預設構造方法。所有的持久化類都必須具有一個預設的構造方法(可以不是public的),這樣NHibernate就可以使用Constructor.Invoke()來執行個體化它們。

[img,11,11]file:///C:/Documents%20and%20Settings/FAST/My%20Documents/1_5%20企業開發架構NHibernate和Spring_Net%20-%20《ASP_NET%202_0+SQL%20SERVER熱門網絡應用開發詳解》%20-%20免費試讀%20-%20book_csdn_net.files/image004.jpg[/img]    提供一個辨別屬性(identifier property)(可選)。

[img,11,11]file:///C:/Documents%20and%20Settings/FAST/My%20Documents/1_5%20企業開發架構NHibernate和Spring_Net%20-%20《ASP_NET%202_0+SQL%20SERVER熱門網絡應用開發詳解》%20-%20免費試讀%20-%20book_csdn_net.files/image004.jpg[/img]    建議使用不是sealed的類(可選)。

3.NHibernate映射對象和關系資料庫之間的映射是用一個XML文檔(XML document)來定義的。這個映射文檔被設計為易讀的,并且可以手工修改。映射語言是以.NET為中心的,意味着映射是按照持久化類的定義來建立的,而非表的定義。在Hibernate中XML映射文檔可以手動定義,也有一些工具來輔助生成,包括Xdoclet、Middlegen和AndroMDA,但是在NHibernate文檔中并沒有上述的輔助工具,不過可以采用MyGeneration這樣的代碼生成工具來生成XML配置文檔。下面是一個映射的例子:

#001 <?xml version="1.0" ?>

#002 <hibernate-mapping xmlns="urn:nhibernate-mapping-2.0" namespace="Eg" assembly="Eg">

#003 <class name="Cat" table="CATS" discriminator-value="C">

#004      <id name="Id" column="uid" type="Int64">

#005         <generator class="hilo"/>

#006      </id>

#007      <discriminator column="subclass" type="Char"/>

#008      <property name="Name" type="Char"/>

#009      <property name="Color" not-null="false"/>

#010      <property name="Sex" not-null="false" update="false"/>

#011      <property name="Weight"/>

#012      <many-to-one name="Mate" column="mate_id"/>

#013      <set name="Kittens">

#014         <key column="mother_id"/>

#015         <one-to-many class="Cat"/>

#016      </set>

#017      <subclass name="DomesticCat" discriminator-value="D">

#018         <property name="Name" type="String"/>

#019      </subclass>

#020 </class>

#021 </hibernate-mapping>

所有的XML映射都需要使用nhibernate-mapping-2.0 schema。目前的schema可以在NHibernate的資源路徑或者是NHibernate.dll的嵌入資源(Embedded Resource)中找到。NHibernate總是會優先使用嵌入在資源中的schema檔案。在使用VisualStudio.NET時,使用者應該将hibernate-mapping拷貝到C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\ Packages\schemas\xml路徑中,以獲得智能感覺功能。

#002行:hibernate-mapping這個元素包括4個可選的屬性。schema屬性,指明了這個映射所引用的表所在的schema名稱。假若指定了這個屬性,表名會加上所指定的schema的名字擴充為全限定名。假若沒有指定,表名就不會使用全限定名。default-cascade指定了未明确注明cascade屬性的屬性和集合類會采取什麼樣的預設級聯風格。auto-import屬性預設在查詢語言中可以使用非全限定名的類名。default-access告訴使用者怎麼通路屬性值。假若有兩個持久化類,它們的非全限定名是一樣的,應該設定auto-import= "false"。假若把一個“import”過的名字同時對應兩個類,NHibernate會抛出一個異常。

#003行:使用class元素來定義一個持久化類。name是持久化類(或者接口)的全限定名。table是對應的資料庫表名。discriminator-value(可選 - 預設和類名一樣)是一個用于區分不同的子類的值,在有多态行為時使用。

#004行:使用id來辨別主鍵字段,因為被映射的類必須聲明對應資料庫表主鍵字段。大多數類有一個屬性,為每一個執行個體包含唯一的辨別。<id> 元素定義了該屬性到資料庫表主鍵字段的映射。

#005行:必須聲明的 <generator> 子元素是一個.NET類的名字,用來為該持久化類的執行個體生成唯一的辨別。其中hilo(高低位)使用一個高/低位算法來高效地生成Int64、Int32 或者Int16類型的辨別符。給定一個表和字段(預設分别是hibernate_unique_key 和next)作為高位值的來源。高/低位算法生成的辨別符隻在特定的資料庫中是唯一的。

#007行:在“一棵對象繼承樹對應一個表”的政策中,<discriminator>元素是必需的,它聲明了表的識别器字段。識别器字段包含标志值,用于告知持久化層應該為某個特定的行建立哪一個子類的執行個體。隻能使用如下受到限制的類型:String,Char,Int32,Byte,Int16,Boolean,YesNo,TrueFalse。

#008-011行:<property>元素為類聲明了一個持久化的屬性。name是屬性的名字,type(可選)是一個NHibernate類型的名字,not-null(可選)表明這個屬性是否為空,update(可選-預設為true)表明在用于UPDATE的SQL語句中是否包含這個字段。

#012行:通過many-to-one元素,可以定義一種常見的與另一個持久化類的關聯。這種關系模型是多對一關聯(實際上是一個對象引用)。

#013-016行:<set>為集合類辨別,其中discriminator-value(可選 - 預設為類名)用于區分每個獨立的子類的值。

#017行:子類(subclass),多态持久化需要為父類的每個子類都進行聲明。對于上面建議的“每一棵類繼承樹對應一個表”的政策來說,就需要使用<subclass>聲明。

4.NHibernate應用執行個體上面已經編寫好了Cat類和相應的映射檔案,為了正确調用Nhibernate,必須對web.config配置檔案進行配置。具體配置代碼如下:

#001 <xml version="1.0" encoding="utf-8" ?>

#002 <configuration>

#003       <configSections>

#004           <section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System Version=2.0.0.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" />

#005       </configSections>

#006       <nhibernate>

#007           <add

#008                key="hibernate.connection.provider"

                      value="NHibernate.Connection.DriverConnectionProvider" />

#009           <add

#010                key="hibernate.connection.driver_class"

                     value="NHibernate.Driver.SqlClientDriver" />

#011           <add

#012                key="hibernate.connection.connection_string"

                     value="server=localhost;uid=sa;pwd=123;database=Sample" />

#013           <add

#014                key="hibernate.connection.isolation" value="ReadCommitted" />

#015           <add

#016                key="hibernate.dialect" value="NHibernate.Dialect.MsSql2000Dialect" />

#017       </nhibernate>

#018 </configuration>

#012行:hibernate.connection.connection_string的value為連接配接伺服器ConnectoinString。其他的都是Nhibernate運作所必需的配置資訊。

配置完web.config檔案,在測試工程中引用NHibernate.dll和Eg,具體代碼如下。

#001    using System;

#002    using System.Collections.Generic;

#003    using System.Text;

#004   using NHibernate;

#005    using NHibernate.Cfg;

#006    using POJOLibrary;

#007    namespace Test

#008    {

#009        class Program

#010        {

#011            static void Main(string[] args)

#012            { Configuration c = new Configuration();

#013                c.AddAssembly("Eg");

#014                ISessionFactory factory = c.BuildSessionFactory();

#015               ISession s = factory.OpenSession();

#016                ITransaction t = s.BeginTransaction();

#017                Cat cat = new Cat();

#018                cat.Name = “Bolo”;

#019                cat.Color = “Black”;

#020                cat.Sex = “Male” ;

#021                cat.Weight = “12” ;

#022                 s.Save(cat);

#023                t.Commit();}

#024        }

#025    }

NHibernate是通過Isession的實作類來提供功能的,上面代碼通過Itransaction打開一個事務t=s.BeginTransaction(),最後通過調用t.Commit()送出事務,将資料寫入資料庫中。

通過上述NHibernate的一個簡單的應用執行個體可以看到,整個應用程式中沒有寫任何一句SQL語句。

雖然NHibernate目前不是非常的成熟,還沒有達到實用化的水準,它經常在負荷有些大的時候崩潰,但是它脫胎于在Java社群有着巨大影響力的Hibernate,而且NHibernate在實際應用方面确實展現出了它的優勢,基于上述原因NHibernate一定會被越來越多的開發人員所接受,而且一定會被标準化。到目前為止,NHibernate的最新版本為1.1,官方站點http://nhibernate.sourceforge.net/上目前的版本是beta 0.7.0.0。

本文轉自左正部落格園部落格,原文連結:http://www.cnblogs.com/soundcode/archive/2010/12/20/1911867.html,如需轉載請自行聯系原作者