下週就去辦理離職手續了,以前沒有使用過NHibernate,只知道NHibernate是一種ORM框架,可是據說新公司是使用NHibernate在作項目,因此,我就網上找資料學習一下NHibernate,在此以筆記的形式,記錄本身的學習過程,一來供本身之後備忘用,而來但願對一樣準備學習NHibernate的同行門有所幫助或提供借鑑。html
NHibernate是一個面向.NET環境的對象/關係數據庫映射工具。對象/關係數據庫映射(object/relational mapping,ORM)這個術語表示一種技術,用來把對象模型表示的對象映射到基於SQL的關係模型數據結構中去。數據庫
NHibernate 是一個基於.Net 的針對關係型數據庫的對象持久化類庫。NHibernate 來源於很是優秀的基於Java的Hibernate 關係型持久化工具。 編程
NHibernate的目標主要是用於與數據持久化相關的編程任務,可以使開發人員從原來枯燥的SQL語句的編寫中解放出來,解放出來的精力可讓開發人員投入到業務邏輯的實現上。session
我最不喜歡理論知識了,仍是那句話,實踐出真知,我將以最直觀的形式來表達。下面開始動手來構建咱們的NHibernate應用程序。數據結構
開發環境:Win七、VS20十二、Sqlserver2008架構
我這裏使用asp.net mvc項目mvc
而後再依次分別新建3個類庫項目,Shop.Domain,Shop.Data,Shop.Businessapp
最終效果圖以下:框架
採用傳統三層架構asp.net
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
安裝完成以後,自動添加了以下引用:
爲了省事,數據庫,我就直接使用northwnd.mdf了,下載地址:http://files.cnblogs.com/files/jiekzou/northwnd.zip,數據庫——附加
關於NorthWind表和字段的說明請查看:http://www.cnblogs.com/pnljs/archive/2012/04/26/2471046.html
打開本項目解決方案所在文件夾位置: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,用於建立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>
運行程序,效果圖:
感冒一週了還沒好,人好難受,可憐我還在電腦旁邊工做着,今天就暫時先寫到這裏了,寫博客確實是很耗時的工做。