NHibernate完全靠配置文件獲取其所需的一切信息,其中映射文件,是其獲取數據庫與C#程序關系的所有信息來源。
一、簡單映射
下面先來一個簡單的例子,然后隨着不斷地對這個例子修修改改,從而真正了解映射文件。具體的資料可以查看http://www.cnblogs.com/kissdodog/archive/2013/02/21/2919886.html
先來看一張表:
映射文件Product.hbm.xml:
<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"> <class name="Model.ProductModel, Model" table="Product"> <id name="ProductId" column="ProductId" type="Int32"> <generator class="native"/> </id> <property name="ProductName" column="ProductName" type="String"/> <property name="ProductPrice" column="ProductPrice" type="float"/> <property name="ProductDiscount" column="ProductDiscount" type="float"/> <!--這個屬性沒有與之對應的列,其列為ProductPrice * ProductDiscount相乘得來--> <property name="ActualPrice" formula="ProductPrice * ProductDiscount" type="float"/> </class> </hibernate-mapping>
PersonModel.cs:
namespace Model { public class ProductModel { public virtual int ProductId { get; set; } public virtual string ProductName { get; set; } public virtual float ProductPrice { get; set; } public virtual float ProductDiscount { get; set; } public virtual float ActualPrice { get; set; } //數據庫里並沒有這個字段 } }
在這里要注意下最后一個字段,數據庫里並沒有這個字段。
ProductDao.cs:
public class ProductDao { public ProductModel GetProduct(int Id) { ISession NSession = NHibernateHelper.GetSession(); return NSession.Get<ProductModel>(Id); } }
Program.cs:
static void Main(string[] args) { ProductDao dao = new ProductDao(); ProductModel pm = dao.GetProduct(1); Console.WriteLine(pm.ProductId + " " + pm.ProductName + " " + pm.ProductPrice + " " + pm.ProductDiscount + " " + pm.ActualPrice); }
顯示結果如下:
你可能奇怪,為什么最后一個字段數據庫沒有,但是為什么也能夠查詢出結果呢?答案在於配置里面的
formula="ProductPrice * ProductDiscount"
這個屬性配置之后,允許某字段的值從其他字段計算獲得。
我們來看看生成的SQL代碼
exec sp_executesql N'SELECT productmod0_.ProductId as ProductId4_0_, productmod0_.ProductName as ProductN2_4_0_, productmod0_.ProductPrice as ProductP3_4_0_, productmod0_.ProductDiscount as ProductD4_4_0_, productmod0_.ProductPrice * productmod0_.ProductDiscount as formula0_0_ FROM Product productmod0_ WHERE productmod0_.ProductId=@p0',N'@p0 int',@p0=1 --以上SQL代碼相當於 SELECT ProductId,ProductName,ProductPrice,ProductDiscount, ProductPrice * ProductDiscount AS formula FROM Product
其實,這是NHibernate根據我們的配置,幫我們生成了SQL語句,計算出另外的字段並綁定的對應的屬性當中。
下面我們開始來不斷更改,以了解更多的NHibernate配置的作用。
我們將Product.hbm.xml的第一行加上下面這一句:
select-before-update="true"
<class name="Model.ProductModel, Model" table="Product" select-before-update="true">
然后PersonDao.cs增加此方法:
public void UpdateProduct(ProductModel product) { ISession NSession = NHibernateHelper.GetSession(); NSession.Update(product); NSession.Flush(); }
用於更新一個Product。
Program.cs:
static void Main(string[] args) { ProductDao dao = new ProductDao(); ProductModel pm = dao.GetProduct(1); dao.UpdateProduct(pm); }
對於此操作,SQL Server Profiler檢測到執行了如下語句:
exec sp_executesql N'SELECT productmod0_.ProductId as ProductId4_0_, productmod0_.ProductName as ProductN2_4_0_, productmod0_.ProductPrice as ProductP3_4_0_, productmod0_.ProductDiscount as ProductD4_4_0_, productmod0_.ProductPrice * productmod0_.ProductDiscount as formula0_0_ FROM Product productmod0_ WHERE productmod0_.ProductId=@p0',N'@p0 int',@p0=1 --相當於如下語句 SELECT ProductId,ProductName,ProductPrice,ProductDiscount FROM Product WHERE ProductId = 1
而當我們去掉
select-before-update
或者將其值設置為flase時,就會直接執行UPDATE語句。select-before-update的作用在於,控制在UPDATE語句之前是否先執行一次查詢,以檢查對象是否有變化,當數據發生變化之后才UPDATE,否則不UPDATE。
二、聯合主鍵
新建一張表如下:
以上3列數據都是NVarchar()類型。
下面來看配置映射文件:
Composite.hbm.xml
<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"> <class name="Model.CompositeModel, Model" table="Composite"> <composite-id name="Pk" class="Model.PKModel, Model"> //name為主實體類的屬性名 <key-property name="Id1" type="String" column="Id1"/> <key-property name="Id2" type="String" column="Id2"/> </composite-id> <property name="Name" column="Name" type="String"/> </class> </hibernate-mapping>
CompositeModel.cs
public class CompositeModel { public virtual PKModel Pk { get; set; } public virtual string Name { get; set; } }
PKModel.cs
public class PKModel { public virtual string Id1 { get; set; } public virtual string Id2 { get; set; } /// <summary> /// 判斷兩個對象是否相同,這個方法需要重寫 /// </summary> /// <param name="obj">進行比較的對象</param> /// <returns>真true或假false</returns> public override bool Equals(object obj) { if (obj is PKModel) { PKModel pk = obj as PKModel; if (this.Id1 == pk.Id1 && this.Id2 == pk.Id2) { return true; } } return false; } public override int GetHashCode() { return base.GetHashCode(); } }
操作:
class Program { static void Main(string[] args) { ISessionFactory _sessionFactory = new Configuration().Configure().BuildSessionFactory(); using(ISession NSession = _sessionFactory.OpenSession()) { IList<CompositeModel> ListComposite = NSession.Query<CompositeModel>().ToList(); foreach (var c in ListComposite) { Console.WriteLine(c.Name); } //查詢單條 PKModel pk = new PKModel(); pk.Id1 = "01"; pk.Id2 = "1"; CompositeModel m = NSession.Get<CompositeModel>(pk); Console.WriteLine(m.Name); } Console.ReadKey(); } }
輸出:
要點:1、聯合主鍵提取出來作為一個類
2、要重寫兩個方法