下周就去辦理離職手續了,之前沒有使用過NHibernate,只知道NHibernate是一種ORM框架,但是聽說新公司是使用NHibernate在做項目,所以,我就網上找資料學習一下NHibernate,在此以筆記的形式,記錄自己的學習過程,一來供自己以后備忘用,而來希望對同樣准備學習NHibernate的同行門有所幫助或提供借鑒。
什么是Nhibernate?
NHibernate是一個面向.NET環境的對象/關系數據庫映射工具。對象/關系數據庫映射(object/relational mapping,ORM)這個術語表示一種技術,用來把對象模型表示的對象映射到基於SQL的關系模型數據結構中去。
NHibernate 是一個基於.Net 的針對關系型數據庫的對象持久化類庫。NHibernate 來源於非常優秀的基於Java的Hibernate 關系型持久化工具。
NHibernate的目標主要是用於與數據持久化相關的編程任務,能夠使開發人員從原來枯燥的SQL語句的編寫中解放出來,解放出來的精力可以讓開發人員投入到業務邏輯的實現上。
我最不喜歡理論知識了,還是那句話,實踐出真知,我將以最直觀的形式來表達。下面開始動手來構建我們的NHibernate應用程序。
開發環境:Win7、VS2012、Sqlserver2008
搭建項目
我這里使用asp.net mvc項目
然后再依次分別新建3個類庫項目,Shop.Domain,Shop.Data,Shop.Business
最終效果圖如下:
項目架構說明
采用傳統三層架構
Shop.Domain:數據實體和數據庫映射文件。也有人叫做領域層。
Shop.Data:數據層,存放數據庫的操作及Nhibernate輔助類。引用Iesi.Collections.dll,NHibernate.dll和類庫Shop.Domain
Shop.Business:業務邏輯類。引用類庫項目Shop.Domain, Shop.Data
Shop.WebSite:測試項目。需引用Iesi.Collections.dll,NHibernate.dll和類庫項目Shop.Domain, Shop.Business
下載Nhibernate
安裝完成之后,自動添加了如下引用:
數據庫設計
為了省事,數據庫,我就直接使用northwnd.mdf了,下載地址:http://files.cnblogs.com/files/jiekzou/northwnd.zip,數據庫——附加
關於NorthWind表和字段的說明請查看:http://www.cnblogs.com/pnljs/archive/2012/04/26/2471046.html
Nhibernate數據庫配置
打開本項目解決方案所在文件夾位置:E:\WorkSpace\Study\Webs\MVC\Shop,會發現有一個packages文件夾,打開此packages文件夾,
會看到一個NHibernate.4.0.3.4000文件夾,打開如下圖:
這里使用的是SQL Server2008,所以我們使用MSSQL.cfg.xml文件,將此文件復制到Shop.WebSite應用程序根目錄,然后重命名為hibernate.cfg.xml.,修改hibernate.cfg.xml
注意需根據自己數據庫的實例名修改,並添加mapping節點,其他的設置,可根據需要進行添加。
修改后如下(我對配置文件都加上了注釋):
<?xml version="1.0" encoding="utf-8"?> <!-- This template was written to work with NHibernate.Test. Copy the template to your NHibernate.Test project folder and rename it in hibernate.cfg.xml and change it for your own use before compile tests in VisualStudio. --> <!-- This is the System.Data.dll provider for SQL Server --> <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2" > <session-factory> <!--定制數據庫IDriver的類型.--> <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property> <!--連接字符串--> <property name="connection.connection_string"> Server=.;database=Northwind;uid=sa;pwd=yujie1127 </property> <!--NHibernate方言(Dialect)的類名 - 可以讓NHibernate使用某些特定的數據庫平台的特性--> <property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property> <!--指定映射文檔中所在程序集--> <mapping assembly="Shop.Domain"/> </session-factory> </hibernate-configuration>
最后,記得修改hibernate.cfg.xml文件的屬性,
NHibernateHelper輔助類
這里編寫一個簡單的輔助類NHibernateHelper,用於創建ISessionFactory和配置ISessionFactory,並打開一個新的ISession的方法。在Shop.Data項目下新建一個類NHibernateHelper,代碼如下:
using NHibernate; using NHibernate.Cfg; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;
namespace Shop.Data { public class NHibernateHelper { private ISessionFactory _sessionFactory; public NHibernateHelper() { //創建ISessionFactory _sessionFactory = GetSessionFactory(); } /// <summary> /// 創建ISessionFactory /// </summary> /// <returns></returns> public ISessionFactory GetSessionFactory() { //配置ISessionFactory return (new Configuration()).Configure().BuildSessionFactory(); } /// <summary> /// 打開ISession /// </summary> /// <returns></returns> public ISession GetSession() { return _sessionFactory.OpenSession(); } } }
持久化類
為客戶實體創建持久化類Customers。在項目Shop.Domain中新建文件夾Entities,然后新建類Customers,這里為了偷懶,我就使用動軟工具生成代碼如下:
注意:NHibernate默認使用代理功能,要求持久化類不是sealed的,而且其公共方法、屬性和事件聲明為virtual。在這里,類中的字段要設置為virtual,否則出現“NHibernate.InvalidProxyTypeException”類型的異常在 Shop.Data.dll 中發生,但未在用戶代碼中進行處理
public class Customers { #region Model private string _customerid; private string _companyname; private string _contactname; private string _contacttitle; private string _address; private string _city; private string _region; private string _postalcode; private string _country; private string _phone; private string _fax;
/// <summary> /// 客戶ID 主鍵 /// </summary> public virtual string CustomerID { set { _customerid = value; } get { return _customerid; } } /// <summary> /// 公司 /// </summary> public virtual string CompanyName { set { _companyname = value; } get { return _companyname; } } /// <summary> /// 客戶姓名 /// </summary> public virtual string ContactName { set { _contactname = value; } get { return _contactname; } } /// <summary> /// 客戶頭銜 /// </summary> public virtual string ContactTitle { set { _contacttitle = value; } get { return _contacttitle; } } /// <summary> /// 聯系地址 /// </summary> public virtual string Address { set { _address = value; } get { return _address; } } /// <summary> /// 所在城市 /// </summary> public virtual string City { set { _city = value; } get { return _city; } } /// <summary> /// 所在地區 /// </summary> public virtual string Region { set { _region = value; } get { return _region; } } /// <summary> /// 郵編 /// </summary> public virtual string PostalCode { set { _postalcode = value; } get { return _postalcode; } } /// <summary> /// 國籍 /// </summary> public virtual string Country { set { _country = value; } get { return _country; } } /// <summary> /// 電話 /// </summary> public virtual string Phone { set { _phone = value; } get { return _phone; } } /// <summary> /// 傳真 /// </summary> public virtual string Fax { set { _fax = value; } get { return _fax; } } #endregion Model }
編寫映射文件
編寫NHibernate配置文件智能提示的功能。只要在下載的NHibernate里找到configuration.xsd和nhibernate-mapping.xsd兩個文件並復制到vs安裝目錄下,如D:\Program Files (x86)\Microsoft Visual Studio 11.0\Xml\Schemas目錄即可。
此時,你在nhibernate的配置文件中就有智能提示功能了。

nhibernate如何知道持久化類和數據庫表的對應關系的呢?這就要通過映射文件來完 成這個任務了,映射文件包含了對象/關系映射所需的元數據。元數據包含持久化類的聲明和屬性到數據庫的映射。映射文件告訴nhibernate它應該訪問 數據庫里面的哪個表及使用表里面的哪些字段。
那么我們編寫Customers持久化類的映射文件,注意映射文件以.hbm.xml結尾。如Customers.hbm.xml
我同樣使用動軟代碼生成工具生成映射文件,代碼如下:
<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Shop.Domain" namespace="Shop.Domain.Entities"> <!--類的全稱,程序集,數據庫表名稱--> <class name="Shop.Domain.Entities.Customers, Shop.Domain" table="Customers"> <id name="CustomerID" column="CustomerID" type="string" /> <property name="CompanyName" column="CompanyName" type="string" /> <property name="ContactName" column="ContactName" type="string" /> <property name="ContactTitle" column="ContactTitle" type="string" /> <property name="Address" column="Address" type="string" /> <property name="City" column="City" type="string"/> <property name="Region" column="Region" type="string"/> <property name="PostalCode" column="PostalCode" type="string"/> <property name="Country" column="Country" type="string" /> <property name="Phone" column="Phone" type="string" /> <property name="Fax" column="Fax" type="string" /> </class> </hibernate-mapping>
最后記得給此映射文件設置屬性
添加數據訪問層類CustomersData.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using NHibernate; using NHibernate.Linq; using NHibernate.Cfg; using System.Linq.Expressions; using Shop.Domain.Entities; namespace Shop.Data { public class CustomersData {
/// <summary>
/// 根據條件得到客戶信息集合
/// </summary>
/// <param name="where">條件</param>
/// <returns>客戶信息集合</returns>
public IList<Customers> GetCustomerList(Expression<Func<Customers, bool>> where)
{
try
{
NHibernateHelper nhibernateHelper = new NHibernateHelper();
ISession session = nhibernateHelper.GetSession();
return session.Query<Customers>().Select(x=>new Customers { ContactName=x.ContactName,City=x.City,Address=x.Address,Phone=x.Phone,CompanyName=x.CompanyName,Country=x.Country}).Where(where).ToList();
}
catch (Exception ex)
{
throw ex;
}
}
}
}
添加業務邏輯層類CustomersBusiness.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading.Tasks; using Shop.Data; using Shop.Domain.Entities; namespace Shop.Business { public class CustomersBusiness { private CustomersData _customersData; public CustomersBusiness() { _customersData = new CustomersData(); }
/// <summary>
/// 根據條件得到客戶信息集合
/// </summary>
/// <param name="where">條件</param>
/// <returns>客戶信息集合</returns>
public IList<Customers> GetCustomerList(Expression<Func<Customers, bool>> where)
{
return _customersData.GetCustomerList(where);
}
}
}
添加控制器:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using Shop.Business; using Shop.Domain.Entities; namespace Shop.Controllers { public class CustomersController : Controller { CustomersBusiness customersBusiness = new CustomersBusiness(); // // GET: /Customer/ public ActionResult Index() { var result = customersBusiness.GetCustomerList(c => 1 == 1); return View(result); }
}
}
添加視圖Index:
@model IEnumerable<Shop.Domain.Entities.Customers> @{ ViewBag.Title = "Index"; } <h2>Index</h2> <p> @Html.ActionLink("Create New", "Create") </p> <table> <tr> <th> @Html.DisplayNameFor(model => model.CompanyName) </th> <th> @Html.DisplayNameFor(model => model.ContactName) </th> <th> @Html.DisplayNameFor(model => model.Address) </th> <th> @Html.DisplayNameFor(model => model.City) </th> <th> @Html.DisplayNameFor(model => model.Country) </th> <th> @Html.DisplayNameFor(model => model.Phone) </th> <th style="width:180px;"></th> </tr> @foreach (var item in Model) { <tr> <td> @Html.DisplayFor(modelItem => item.CompanyName) </td> <td> @Html.DisplayFor(modelItem => item.ContactName) </td> <td> @Html.DisplayFor(modelItem => item.Address) </td> <td> @Html.DisplayFor(modelItem => item.City) </td> <td> @Html.DisplayFor(modelItem => item.Country) </td> <td> @Html.DisplayFor(modelItem => item.Phone) </td> <td> @Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) | @Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) | @Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ }) </td> </tr> } </table>
運行程序,效果圖:

感冒一周了還沒好,人好難受,可憐我還在電腦旁邊工作着,今天就暫時先寫到這里了,寫博客確實是很耗時的工作。
