Nhibernate學習教程(2)-- 第一個NHibernate程序
NHibernate之旅(2):第一個NHibernate程序
本節內容
- 開始使用NHibernate
- 1.獲取NHibernate
- 2.建立數據庫表
- 3.創建C#類庫項目
- 4.設計Domain
- 4-1.設計持久化類
- 4-2.編寫映射文件
- 5.數據訪問層
- 5-1.輔助類
- 5-2.編寫操作
- 6.數據訪問層的測試
- 6-1.配置NHibernate
- 6-2.測試
- 結語
開始使用NHibernate
我們親自動手,一步一步搭建一個NHibernate程序來,我以一個實際場景電子交易程序來模擬,客戶/訂單/產品的經典組合。由於是第一次使用NHibernate,所以我們的目的是映射一張表並完成使用NHibernate來讀取數據,下面的一幅圖片給了我們第一印象。我們按照基本開發軟件思想的流程一步一步完成。
我使用的開發環境:Microsoft Visual Studio 2008 SP1、SQL Server 2008 Express、NHibernate 2.1.1GA。
1.獲取NHibernate
使用官方2009年10月31日最新發布的NHibernate-2.1.1.GA版本。如果你第一次使用NHibernate,先到這裏下載NHibernate最新版本(包括源碼、發布版本、參考文檔、API文檔,可選擇下載)。如果用到NHibernate的擴展項目到這裏下載獲得NHibernate Contrib最新版本。NHibernate-2.1.1.GA是.NET2.0平臺的最後一個版本,關於NHibernate-2.1.1.GA的更多信息請點擊這裏。
關於NHibernate2.1版本的一些說明:
NHibernate2.1版本改變了ByteCode延遲加載機制,有三種3種IoC框架動態代理方式,分別為:Castle框架、LinFu框架、Spring.Net框架。我們只要選擇一種,在配置文件中配置proxyfactory.factory_class節點。
如果使用Castle.DynamicProxy2動態代理,引用NHibernate.ByteCode.Castle.dll程序集並配置proxyfactory.factory_class節點為<property name="proxyfactory.factory_class"> NHibernate.ByteCode.Castle.ProxyFactoryFactory,NHibernate.ByteCode.Castle</property>
如果使用LinFu.DynamicProxy動態代理,引用NHibernate.ByteCode.LinFu.dll程序集並配置proxyfactory.factory_class節點為<property name="proxyfactory.factory_class"> NHibernate.ByteCode.LinFu.ProxyFactoryFactory,NHibernate.ByteCode.LinFu</property>
如果使用Spring.Aop動態代理,引用NHibernate.ByteCode.Spring.dll程序集並配置proxyfactory.factory_class節點為<property name="proxyfactory.factory_class"> NHibernate.ByteCode.Spring.ProxyFactoryFactory,NHibernate.ByteCode.Spring</property>
另外NHibernate2.1要求.NET2.0 SP1以上版本 (System.DateTimeOffset),請使用VS2005的,務必打上Sp1補丁。推薦使用VS2008以上版本。
2.建立數據庫表
由於第一次使用,還是按照我們傳統的從數據庫表配置吧。
打開SQL Server Management Studio Express,新建一個新的數據庫NHibernateSample,創建四個表:分別為客戶表、訂單表、訂單產品表、產品表。
3.創建C#類庫項目
由於是我們第一個程序,所以我沒有按照Domain Driver Design方法去設計這個程序,按照大家的常規思想來實現的,以後有機會再介紹Domain Driver Design設計。
使用VS2008創建C#類庫的項目,命名為NHibernateSample。打開項目文件夾,在其項目文件目錄上新建SharedLibs文件夾,把下載NHibernate相關程序集文件拷貝到SharedLibs文件夾下。如下圖,這裏我選擇Castle框架動態代理:
創建項目,結構如下:
- Domain(領域模型):用於持久化類和O/R Mapping操作
- Data(Data Access Layer數據訪問層):定義對象的CRUD操作
- Data.Test(數據訪問層測試):對數據訪問層的測試,這裏我使用Nunit單元測試框架
- Web:Web頁面(這篇文章中暫未實現,請參考我的博客其他文章)
4.設計Domain
4-1.編寫持久化類
按簡單傳統.NET對象(POCOs,Plain Old CLR Objects(Plain Ordinary CLR Objects))模型編程時需要持久化類。在NHibernate中,POCO通過.NET的屬性機制存取數據,就可以把它映射成為數據庫表。
現在為Customer編寫持久化類來映射成為數據庫表。新建一個Customer.cs類文件:
namespace NHibernateSample.Domain.Entities
{
public class Customer
{
public virtual int Id { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
}
}
4-2.編寫映射文件
NHibernate要知道怎樣去加載和存儲持久化類的對象。這正是NHibernate映射文件發揮作用的地方。映射文件包含了對象/關系映射所需的元數據。元數據包含持久化類的聲明和屬性到數據庫的映射。映射文件告訴NHibernate它應該訪問數據庫裏面的哪個表及使用表裏面的哪些字段。
這裏,我為Customer.cs類編寫映射文件。新建一XML文件,命名為Customer.hbm.xml:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="NHibernateSample.Domain"
namespace="NHibernateSample.Domain.Entities">
<class name ="Customer">
<id name="Id" column ="CustomerId">
<generator class ="native"/>
</id>
<property name ="FirstName"/>
<property name ="LastName"/>
</class>
</hibernate-mapping>
5.編寫數據訪問層
5-1.輔助類
我們現在可以開始NHibernate了。首先,我們要從ISessionFactory中獲取一個ISession(NHibernate的工作單元)。ISessionFactory可以創建並打開新的Session。一個Session代表一個單線程的單元操作。 ISessionFactory是線程安全的,很多線程可以同時訪問它。ISession不是線程安全的,它代表與數據庫之間的一次操作。ISession通過ISessionFactory打開,在所有的工作完成後,需要關閉。 ISessionFactory通常是個線程安全的全局對象,只需要被實例化一次。我們可以使用GoF23中的單例(Singleton)模式在程序中創建ISessionFactory。這個實例我編寫了一個輔助類NHibernateHelper 用於創建ISessionFactory並配置ISessionFactory和打開一個新的Session單線程的方法,之後在每個數據操作類可以使用這個輔助類創建ISession 。
public class NHibernateHelper
{
private ISessionFactory _sessionFactory;
public NHibernateHelper()
{
_sessionFactory = GetSessionFactory();
}
private ISessionFactory GetSessionFactory()
{
return (new Configuration()).Configure().BuildSessionFactory();
}
public ISession GetSession()
{
return _sessionFactory.OpenSession();
}
}
5-2.編寫操作
在Data中新建一類NHibernateSample.cs,編寫一方法GetCustomerId用於讀取客戶信息。在編寫方法之前,我們需要初始化Session。
protected ISession Session { get; set; }
public NHibernateSample(ISession session)
{
Session = session;
}
NHibernate有不同的方法來從數據庫中取回對象。最靈活的方式是使用NHibernate查詢語言(HQL),是完全基於面向對象的SQL。
public void CreateCustomer(Customer customer)
{
Session.Save(customer);
Session.Flush();
}
public Customer GetCustomerById(int customerId)
{
return Session.Get<Customer>(customerId);
}
6.編寫數據訪問層的測試
6-1.配置NHibernate
我們可以幾種方法來保存NHibernate的配置,具體以後來介紹,這裏我們使用hibernate.cfg.xml文件來配置,不過不必擔心,這個文件我們可以在src\NHibernate.Config.Templates文件夾下找到,直接復制到Data.Test中修改一下配置信息和文件輸出屬性就可以了。
<?xml version="1.0" encoding="utf-8"?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2" >
<session-factory>
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<property name="connection.connection_string">
Data Source=.\SQLEXPRESS;Initial Catalog=NHibernateSample;
Integrated Security=True;Pooling=False
</property>
<property name="adonet.batch_size">10</property>
<property name="show_sql">true</property>
<property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
<property name="use_outer_join">true</property>
<property name="command_timeout">10</property>
<property name="query.substitutions">true 1, false 0, yes ‘Y‘, no ‘N‘</property>
<property name="proxyfactory.factory_class">NHibernate.ByteCode.Castle.ProxyFactoryFactory,
NHibernate.ByteCode.Castle</property>
<mapping assembly="NHibernateSample.Domain"/>
</session-factory>
</hibernate-configuration>
6-2.測試
好了,終於可以使用我們的方法了,這裏新建一個測試類NHibernateSampleFixture.cs來編寫測試用例:調用NHibernateSample類中GetCustomerId方法查詢數據庫中CustomerId為1的客戶,判斷返回客戶的Id是否為1。
[TestFixture]
public class NHibernateSampleFixture
{
private NHibernateSample _sample;
[TestFixtureSetUp]
public void TestFixtureSetup()
{
_sample = new NHibernateSample();
}
[Test]
public void GetCustomerByIdTest()
{
var tempCutomer = new Customer {FirstName = "李", LastName = "永京"};
_sample.CreateCustomer(tempCutomer);
Customer customer = _sample.GetCustomerById(1);
int customerId = customer.Id;
Assert.AreEqual(1,customerId);
}
}
我們使用TestDriven.NET測試一下這個方法:OK,測試通過。這裏我使用NHibernate監視器NHibernate Profiler查看結果:
結語
在這篇文章中,我們使用NHibernate來構建了一個最基本的項目,沒有體現NHibernate更多細節,只描繪了NHibernate的基本面目。當然使用NHibernate有各種各樣的程序架構,我按照一般模式構建的。請大家在實際項目中不要參考關於Session管理部分,本系列未做處理,更多實戰知識以後介紹。
Nhibernate學習教程(2)-- 第一個NHibernate程序