目錄
寫在前面
在耗時兩月,NHibernate系列出爐這篇文章中,很多園友說了Fluent Nhibernate的東東,也激起我的興趣,想對它一探究竟,這里也將Fluent Nhibernate寫成一個系列,記錄自己的學習過程,關於這東東,也是第一次接觸,也只能邊摸索,邊記錄了。如果有描述錯誤的地方,還望多多包涵。
通過Nhibernate的學習,都覺得Nhibernate的使用映射文件的編寫很麻煩,這里通過Fluent Nhibernate的進行對比學習。
Fluent Nhibernate簡介
Fluent Nhibernate下載地址:http://www.fluentnhibernate.org/
在該網站上對Fluent Nhibernate的簡介
Fluent, XML-less, compile safe, automated, convention-based mappings for NHibernate.
Fluent,更少的xml,編譯安全,自動化,基於Nhibernate的映射。
Fluent NHibernate offers an alternative to NHibernate's standard XML mapping files. Rather than writing XML documents (.hbm.xml files), Fluent NHibernate lets you write mappings in strongly typed C# code. This allows for easy refactoring, improved readability and more concise code.
用編程的方式進行配置,讓你能更好的理解,不需要編寫復雜的映射文件,它能完全替換NHibernate的映射文件,讓你在映射的時候能使用C#的強類型方式。
基本配置
測試項目結構

項目結構介紹
Wolfy.Data:項目數據層,存放操作數據庫類,FluentNhibernateHelper
Wolfy.Domain:存放持久化類,及映射類。
Wolfy.UnitTest:單元測試項目
首先使用Nuget安裝Fluent Nhibernate

安裝成功后

Fluent Nhibernate是基於Nhibernate的,所以在安裝Fluent Nhibernate的同時也會將Nhibernate的dll安裝上。此時的Nhibernate的程序集的版本為

Fluent Nhibernate對應的Nhibernate版本為3.3.1.4000
編寫FluentNhibernateHelper類
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using NHibernate; 7 using FluentNHibernate; 8 namespace Wolfy.Data 9 { 10 /// <summary> 11 /// Nhibernate輔助類 12 /// </summary> 13 public class FluentNHibernateHelper 14 { 15 private static ISessionFactory _sessionFactory; 16 private static ISession _session; 17 private static object _objLock = new object(); 18 private FluentNHibernateHelper() 19 { 20 21 } 22 /// <summary> 23 /// 創建ISessionFactory 24 /// </summary> 25 /// <returns></returns> 26 public static ISessionFactory GetSessionFactory() 27 { 28 if (_sessionFactory == null) 29 { 30 lock (_objLock) 31 { 32 if (_sessionFactory == null) 33 { 34 //配置ISessionFactory 35 _sessionFactory = FluentNHibernate.Cfg.Fluently.Configure() 36 //數據庫配置 37 .Database( 38 //方言 39 FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2012 40 //連接字符串 41 .ConnectionString( 42 c => c.Server(".") 43 .Password("sa") 44 .Username("sa") 45 .Database("Shop") 46 .TrustedConnection() 47 ) 48 //是否顯示sql 49 .ShowSql() 50 ) 51 //映射程序集 52 .Mappings(m => m.FluentMappings 53 .AddFromAssembly(System.Reflection.Assembly.Load("Wolfy.Domain")) 54 .ExportTo("c:\\")) 55 .BuildSessionFactory(); 56 57 } 58 } 59 } 60 return _sessionFactory; 61 62 } 63 /// <summary> 64 /// 重置Session 65 /// </summary> 66 /// <returns></returns> 67 public static ISession ResetSession() 68 { 69 if (_session.IsOpen) 70 _session.Close(); 71 _session = _sessionFactory.OpenSession(); 72 return _session; 73 } 74 /// <summary> 75 /// 打開ISession 76 /// </summary> 77 /// <returns></returns> 78 public static ISession GetSession() 79 { 80 GetSessionFactory(); 81 if (_session == null) 82 { 83 lock (_objLock) 84 { 85 if (_session == null) 86 { 87 _session = _sessionFactory.OpenSession(); 88 } 89 } 90 } 91 return _session; 92 } 93 94 } 95 }
CreateSessionFactory方法對應Nhibernate的配置文件,通過代碼的方式指定Nhibernate的配置信息,使用起來更方便。下面為之前學習Nhibernate時寫的配置文件,不明白的可以回到NHIbernate系列文章去查看。
1 <?xml version="1.0" encoding="utf-8" ?> 2 <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2" > 3 <session-factory> 4 <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property> 5 <property name="connection.connection_string"> 6 server=.;database=shop;uid=sa;pwd=sa 7 </property> 8 <property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property> 9 <mapping assembly="Wolfy.Shop.Domain"/> 10 </session-factory> 11 </hibernate-configuration>
一個例子
Customer持久化類
1 /// <summary> 2 /// 客戶持久化類 3 /// </summary> 4 public class Customer 5 { 6 public virtual Guid CustomerID { set; get; } 7 public virtual int Version { set; get; } 8 public virtual string CustomerName { set; get; } 9 public virtual string CustomerAddress { set; get; } 10 }
添加映射類
CustomerMapping.cs
1 /// <summary> 2 /// Customer映射實體類,需要集成ClassMap泛型類 3 /// </summary> 4 public class CustomerMapping : ClassMap<Customer> 5 { 6 /// <summary> 7 /// 映射關系實體類的構造函數 8 /// 在構造函數中處理好映射關系 9 /// </summary> 10 public CustomerMapping() 11 { 12 //指定持久化類對應的數據表 13 Table("TB_Customer"); 14 //自動增長的id 15 //Id(i => i.CustomerID); 16 //映射關系 17 Id<Guid>("CustomerID").GeneratedBy.Guid(); 18 Map(m => m.CustomerAddress).Length(50).Nullable(); 19 Map(m => m.CustomerName).Length(32).Nullable(); 20 Map(m => m.Version); 21 } 22 }
映射配置類需繼承ClassMap泛型類,在構造函數中可以通過Map方法,指定字段與數據表字段的對應關系,Map有兩個重載方法,如下:
1 // 2 // 摘要: 3 // Create a property mapping. 4 // 5 // 參數: 6 // memberExpression: 7 // Property to map 8 public PropertyPart Map(Expression<Func<T, object>> memberExpression); 9 // 10 // 摘要: 11 // Create a property mapping. 12 // 13 // 參數: 14 // memberExpression: 15 // Property to map 16 // 17 // columnName: 18 // Property column name 19 public PropertyPart Map(Expression<Func<T, object>> memberExpression, string columnName);
這里有個需要注意的地方,如果不指定映射的數據表,默認持久化類要與數據庫中的表名對應,比如持久化類名為Customer,而數據表名為TB_Customer,則有以下異常: could not execute batch command.[SQL: SQL not available]

意思就是對應關系找不到。解決辦法就是指定映射的數據表名。
數據層CustomerData類添加AddCustomer方法
1 /// <summary> 2 /// 客戶類數據層 3 /// </summary> 4 public class CustomerData 5 { 6 /// <summary> 7 /// 添加客戶對象 8 /// </summary> 9 /// <param name="customer"></param> 10 /// <returns></returns> 11 public bool AddCustomer(Customer customer) 12 { 13 ISession session = FluentNHibernateHelper.GetSession(); 14 using (var trans = session.BeginTransaction()) 15 { 16 try 17 { 18 session.SaveOrUpdate(customer); 19 session.Flush(); 20 trans.Commit(); 21 return true; 22 } 23 catch (Exception) 24 { 25 trans.Rollback(); 26 return false; 27 } 28 } 29 30 } 31 }
你會發現,方法與使用Nhibernate的時候的方法實現沒什么區別,代碼相同,唯一的區別就是配置文件的編寫方式,一種是使用代碼實現,一種是使用xml文件進行配置的。
單元測試
1 using System; 2 using Microsoft.VisualStudio.TestTools.UnitTesting; 3 using Wolfy.Domain.Entities; 4 using Wolfy.Data; 5 namespace Wolfy.UnitTest 6 { 7 [TestClass] 8 public class CustomerDataTest 9 { 10 private CustomerData _customerData; 11 public CustomerDataTest() 12 { 13 _customerData = new CustomerData(); 14 } 15 [TestMethod] 16 public void AddCustomerTest() 17 { 18 var result = _customerData.AddCustomer( 19 new TB_Customer() 20 { 21 Version = 1, 22 CustomerName = "wolfy", 23 CustomerAddress = "中國 北京", 24 CustomerID = Guid.NewGuid() 25 } 26 ); 27 Assert.IsTrue(result); 28 } 29 } 30 }
描述:通過數據層的AddCustomer方法向數據庫中添加一個客戶對象,並獲得添加結果,斷言結果為true,則測試通過。
運行測試,測試結果

生成的sql語句
1 exec sp_executesql N'INSERT INTO [TB_Customer] 2 (CustomerAddress, CustomerName, Version, CustomerID) 3 VALUES (@p0, @p1, @p2, @p3)', 4 N'@p0 nvarchar(4000), 5 @p1 nvarchar(4000), 6 @p2 int, 7 @p3 uniqueidentifier', 8 @p0=N'中國 北京', 9 @p1=N'wolfy', 10 @p2=1, 11 @p3='F15D04CF-300F-45C1-A774-3394CBA08155'
回頭看一下,在FluentNhibernateHelper中,有這樣一句代碼:
1 //映射程序集 2 .Mappings(m => m.FluentMappings 3 .AddFromAssembly(System.Reflection.Assembly.Load("Wolfy.Domain")) 4 .ExportTo("c:\\"))
意思是將映射文件導出到c盤下,那么我們看一下c盤下生成了什么?

你會發現此時的xml文件正是Nhibernate中對應持久化類的映射文件,內容為:
1 <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"> 2 <class xmlns="urn:nhibernate-mapping-2.2" name="Wolfy.Domain.Entities.Customer, Wolfy.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="TB_Customer"> 3 <id type="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 4 <column name="CustomerID" /> 5 <generator class="guid" /> 6 </id> 7 <property name="CustomerAddress" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 8 <column name="CustomerAddress" length="50" not-null="false" /> 9 </property> 10 <property name="CustomerName" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 11 <column name="CustomerName" length="32" not-null="false" /> 12 </property> 13 <property name="Version" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 14 <column name="Version" /> 15 </property> 16 </class> 17 </hibernate-mapping>
總結
關於Fluent Nhibernate的基本使用就介紹到這里,不管怎樣,先讓第一個程序跑起來,才算是走好了第一步。
本篇內容學習了如何使用Fluent Nhibernate生成配置文件及映射文件。
參考文章
http://www.cnblogs.com/inday/archive/2009/08/04/Study-Fluent-NHibernate-Start.html
