本節內容
開始使用NHibernate
1.獲取NHibernate
2.建立數據庫表
3.創建C#類庫項目
4.編寫DomainModel層
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.0最新版。
1.獲取NHibernate
使用官方2008年9月29日最新發布的NHibernate-2.0.1.GA版本。你可以到這裡下載獲得NHibernate最新版本。
2.建立數據庫表
打開SQL Server Management Studio,新建一個新的數據庫NHibernateSample,創建四個表:分別為客戶表、訂單表、訂單產品表、產品表。
注:源碼中附有創建數據庫腳本。
3.創建C#類庫項目注意為什麼創建C#類庫項目呢?在現在軟件設計中,大多數都是采用多層架構來設計,比較經典的三層架構(頁面表示層,業務邏輯層,數據訪問層)通常而言業務邏輯層和數據訪問層都是使用類庫設計,頁面表示層用Web應用程序設計,它引用業務邏輯層和數據訪問層類庫DLL程序集。
使用VS2008創建C#類庫的項目,命名為NHibernateSample。打開項目文件夾,在其項目文件目錄上新建lib文件夾,把下載NHibernate相關程序集文件拷貝到lib文件夾下。如下圖:
創建項目,結構如下:
DomainModel(域模型):用於持久化類和O/R Mapping操作
DAL(Data Access Layer數據訪問層):定義對象的CRUD操作
DAL.Test(數據訪問層測試):對數據訪問層的測試,這裡我使用Nunit單元測試框架
項目引用
DomainModel:引用Iesi.Collections.dll程序集(Set集合在這個程序集中)
DAL:引用NHibernate.dll和Iesi.Collections.dll程序集,DomainModel層引用
DAL.Test:引用NHibernate.dll和Iesi.Collections.dll程序集,nunit.framework.dll程序集(測試框架),DomainModel層和DAL層引用
4.編寫DomainModel層4-1.編寫持久化類
按簡單傳統.NET對象(POCOs,Plain Old CLR Objects(Plain Ordinary CLR Objects))模型編程時需要持久化類,也可以說是DTO(Data Transfer Object,數據傳送對象)模式(這是迄今為止可以工作的最簡單方式)。在NHibernate中,POCO通過.NET的屬性機制存取數據,就可以把它映射成為數據庫表。
現在為Customer編寫持久化類來映射成為數據庫表。新建一個Customer.cs類文件:
namespace DomainModel.Entities
{
public class Customer
{
public virtual int CustomerId { get; set; }
public virtual string Firstname { get; set; }
public virtual string Lastname { get; set; }
}
}
規則
NHibernate使用屬性的getter和setter來實現持久化。
屬性可設置為public、internal、protected、protected internal或private
注意NHibernate默認使用代理功能,要求持久化類不是sealed的,而且其公共方法、屬性和事件聲明為virtual。在這裡,類中的字段要設置為virtual,否則出現“failed: NHibernate.InvalidProxyTypeException : The following types may not be used as proxies: DomainModel.Entities.Customer: method get_CustomerId should be virtual,method set_CustomerId should be virtual”異常。4-2.編寫映射文件小提示我們要為Microsoft Visual Studio 2008添加編寫NHibernate配置文件智能提示的功能。只要在下載的NHibernate裡找到configuration.xsd和nhibernate-mapping.xsd兩個文件並復制到X:\Program Files\Microsoft Visual Studio 9.0\Xml\SchemasX:\Program Files\Microsoft Visual Studio 9.0\Xml\Schemas目錄即可。
NHibernate要知道怎樣去加載和存儲持久化類的對象。這正是NHibernate映射文件發揮作用的地方。映射文件包含了對象/關系映射所需的元數據。元數據包含持久化類的聲明和屬性到數據庫的映射。映射文件告訴NHibernate它應該訪問數據庫裡面的哪個表及使用表裡面的哪些字段。
這裡,我為Customer.cs類編寫映射文件,具體怎麼編寫O/R Mapping文件,請參考NHibernate文檔。新建一XML文件,命名為Customer.hbm.xml:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="DomainModel" namespace="DomainModel">
<class name ="DomainModel.Entities.Customer,DomainModel" table="Customer">
<id name="CustomerId" column="CustomerId" type="Int32" unsaved-value="0">
<generator class ="native"></generator>
</id>
<property name="Firstname" column ="Firstname" type="string" length="50" not-null="false"/>
<property name ="Lastname" column="Lastname" type="string" length="50" not-null="false"/>
</class>
</hibernate-mapping>
注意XML文件的默認生成操作為“內容”,這裡需要修改為“嵌入的資源”生成,使用.NET Reflector查看程序集:
否則出現“ failed: NHibernate.MappingException : No persister for: DomainModel.Entities.Customer”異常。5.編寫數據訪問層5-1.輔助類
我們現在可以開始NHibernate了。首先,我們要從ISessionFactory中獲取一個ISession(NHibernate的工作單元)。ISessionFactory可以創建並打開新的Session。一個Session代表一個單線程的單元操作。ISessionFactory是線程安全的,很多線程可以同時訪問它。ISession不是線程安全的,它代表與數據庫之間的一次操作。ISession通過ISessionFactory打開,在所有的工作完成後,需要關閉。ISessionFactory通常是個線程安全的全局對象,只需要被實例化一次。我們可以使用GoF23中的單例(Singleton)模式在程序中創建ISessionFactory。這個實例我編寫了一個輔助類SessionManager 用於創建ISessionFactory並配置ISessionFactory和打開一個新的Session單線程的方法,之後在每個數據操作類可以使用這個輔助類創建ISession 。
public class SessionManager
{
private ISessionFactory _sessionFactory;
public SessionManager()
{
_sessionFactory = GetSessionFactory();
}
private ISessionFactory GetSessionFactory()
{
return (new Configuration()).Configure().BuildSessionFactory();
}
public ISession GetSession()
{
return _sessionFactory.OpenSession();
}
}
5-2.編寫操作
在DAL層新建一類NHibernateSample.cs,編寫一方法GetCustomerId用於讀取客戶信息。在編寫方法之前,我們需要初始化Session。
private ISession _session;
public ISession Session
{
set
{
_session = value;
}
}
public NHibernateSample(ISession session)
{
_session = session;
}
NHibernate有不同的方法來從數據庫中取回對象。最靈活的方式是使用NHibernate查詢語言(HQL),是完全基於面向對象的SQL。
public Customer GetCustomerById(int customerId)
{
return _session.Get<Customer>(customerId);
}
6.編寫數據訪問層的測試
6-1.配置NHibernate
我們可以幾種方法來保存NHibernate的配置,具體以後來介紹,這裡我們使用hibernate.cfg.xml文件來配置,不過不必擔心,這個文件我們可以在src\NHibernate.Test文件夾下找到,直接復制到DAL.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>
<mapping assembly="DomainModel"/>
</session-factory>
</hibernate-configuration>
注意XML文件的默認“復制到輸出目錄”為“不復制”,這裡需要修改為“始終復制”。否則出現“failed: NHibernate.Cfg.HibernateConfigException : An exception occurred during configuration of persistence layer. ----> System.IO.FileNotFoundException : 未能找到文件“NHibernateSample\NHibernateSample.Data.Test\bin\Debug\hibernate.cfg.xml””異常。
6-2.測試
好了,終於可以使用我們的方法了,這裡新建一個測試類NHibernateSampleFixture.cs來編寫測試用例:調用NHibernateSample類中GetCustomerId方法查詢數據庫中CustomerId為1的客戶,判斷返回客戶的Id是否為1。
using NUnit.Framework;
using DomainModel.Entities;
using NHibernate;
namespace DAL.Test
{
[TestFixture]
public class NHibernateSampleFixture
{
private ISession _session;
private SessionManager _helper;
private NHibernateSample _sample;
[TestFixtureSetUp]
public void TestFixtureSetup()
{
_helper = new SessionManager();
}
[SetUp]
public void Setup()
{
_session = _helper.GetSession();
_sample = new NHibernateSample(_session);
}
[Test]
public void GetCustomerByIdTest()
{
Customer customer = _sample.GetCustomerById(1);
int customerId = customer.CustomerId;
Assert.AreEqual(1,customerId);
}
}
}
我們使用TestDriven.NET測試一下這個方法:OK,測試通過,還輸出了SQL語句(注:我配置NHibernate時設置了show_sql=true輸出SQL語句)。
結語
在這篇文章中,我們使用NHibernate來構建了一個最基本的項目,沒有體現NHibernate更多細節,只描繪了NHibernate的基本面目。當然使用NHibernate有各種各樣的程序架構,我按照一般模式構建的。