ORM利器:NHibernate(三)五部曲+簡單對象CRUD+HQL,ormcrud
前面的兩篇文章中,我們對NHibernate已經做了大致瞭解
《ORM利器:NHibernate(一)簡介》Nhibernate的作用:解決了對象和資料庫的轉化問題
《ORM利器:NHibernate(二)使用CodeSmith快速產生對應檔和映射類 》利用CodeSmith由表匯出映射類(就是通常所說的Entity)和對應檔(告訴你表和對象之間是如何建立一一對應的關係的)。
接下來將會對NHibernate的使用做Demo解析,分為五部曲:
- 建立表。若要把對象轉換為資料庫中的表,自然要有對一個的表。因此,首先要在資料庫中建立把.Net類持久化的對應表。
- 建立類。建立需要被持久化的.Net類.對象。
- 建立對應檔。 描述對象和庫之間的關係,告訴NH怎樣持久化這些類的屬性.
- 建立NH的設定檔,以告訴NH怎樣串連資料庫,以何種方式串連不同種類的資料庫。
- 使用NH提供的API。維護對象和庫之間的關係,對對象的CRUD和對資料庫的DML.
步驟詳情:
第一部:建立表(步驟很簡單,這裡不做解釋)
第二部:建立類+第三部:建立對應檔(本Demo利用CodeSmith自動產生,詳細請參見《ORM利器:NHibernate(二)使用CodeSmith快速產生對應檔和映射類 》)
第四部:建立NH設定檔 主要用於串連資料庫:驅動的提供者、驅動的位置、資料庫的身分識別驗證資訊等,和我們曾經寫過的資料庫連接語句無意,只不過放在了設定檔中而已。而且NH採用代理工廠,針對不同的資料庫產品進行生產,提供了更好的靈活性,如果你需要把SQLServer資料庫,更改為Oracle資料庫,只需要更改相應的配置資訊就可以。
<?xml version="1.0" encoding="utf-8" ?><configuration> <configSession> <section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler,NHibernate" requireParmission="false"/> </configSession> <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2" > <!--Session工廠,使用者層級的對象--> <session-factory name="NHibernate.Test"> <!--驅動是由誰提供的--> <property name="connection.provider">NHibernate.Connection.ConnectionProvider,NHibernate</property> <!--驅動類的位置--> <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property> <!--身分識別驗證登陸--> <property name="connection.connection_string">Server=(local);initial catalog=NHibernate;Integrated Security=SSPI</property> <property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property> <!--是否顯示sql語句--> <property name="show_sql">False</property> <!--代理工廠,針對不同的資料庫產品進行生產--> <property name="proxyfactory.factory_class">NHibernate.ByteCode.Linfu.ProcxyFactoryFactory,NHibernate.ByteCode.Linfu</property> </session-factory> </hibernate-configuration></configuration>
如果你覺得設定檔很複雜、記不住,也沒有關係。NH為我們提供了很多設定檔的模板以供參考,這裡我們採用SQLServer,因此可以參照:Configuration_Templates—MSSQL.cfg.xml
第五部:使用NH提供的API。維護對象和庫之間的關係,對對象的CRUD和對資料庫的DML
1、目錄結構如下:
1)建立類庫Test:
用於存放所有的對象和.NET對應檔(如此處的Person.cs對象,Person.hbm.xml對應檔),為了讓NHibernate能夠找到所有的對應檔,必須設定為“嵌入資源”,產生Test.dll檔案備用。
2)添加引用:
2、添加表單Form1,:
3、表單Form1中的代碼如下所示:
首先,通過config讀取設定檔,讀取所有對應檔,載入程式集(必須是嵌入資源)
其次,通過SessionFactory建立session工廠,負責持久化的串連以及OR映射(該對象的開銷比較大,一般建議用單例模式實現)
然後,通過session建立一個可以用於使用者層級的操作對象。
開啟事務對象trans = session.BeginTransaction();
上面的思路和我們曾經使用過的SQLServer是一個道理。接下來看一下不同點:
以前D層和資料庫打交道的時候,我們通常使用sql語句,而後直接對資料庫進行操作。而在NH中所有的操作(增刪改查)全都是針對“對象”而言的,如果想要把對象儲存在資料庫中,就需要先將對象必須轉化為資料庫能識別的sql語句,由於在SessionFactory中已經儲存了所有的OR映射,ISession能根據相應的方言實現sql語句。
下文的代碼中已經實現了簡單操作對象。主要是通過session的get、save、delete方法來實現。若要實現複雜的查詢不免會比較繁瑣。NHibernate提供了一種強大的查詢語言HQL(Hibernate Query Language),它的文法非常類似於Sql,不同的是只能用於對資料進行查詢操作,不能用於資料增、刪、改。它是完全物件導向的,具備繼承、多態和關聯等特性。
using System;using System.Collections;using System.Collections.Generic;using System.Windows.Forms;using NHibernate;using NHibernate.Cfg;using Test.Model;using System.Linq;namespace WinFormTest{ public partial class Form1 : Form { //建立session ISession session = null; //建立session工廠 ISessionFactory factory = null; //建立事務 ITransaction trans = null; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { //讀取設定檔 //讀取所有對應檔,載入程式集,必須是嵌入資源 Configuration config = new Configuration().AddAssembly("Test.Model"); //建立session工廠,負責持久化的串連以及OR映射,該對象的開銷比較大,一般建議用單例模式實現 factory = config.BuildSessionFactory(); //建立一個可以用於使用者層級的操作對象 session = factory.OpenSession(); } //添加使用者 private void btnAdd_Click(object sender, EventArgs e) { //開啟事務對象 trans = session.BeginTransaction(); //使用NHibernate現有API //體驗過程 try { //對象的執行個體化方式 Person p = new Person(); p.Name = this.txtName.Text; //把對象儲存在資料庫中 //將對象必須轉化為資料庫能識別的sql語句 //由於在SessionFactory中已經儲存了所有的OR映射 //ISession能根據相應的方言實現sql語句 session.Save(p); trans.Commit(); } catch (Exception) { //出錯後,交易回復 trans.Rollback(); } } //查詢使用者 private void btnFind_Click(object sender, EventArgs e) { //trans = session.BeginTransaction(); //尋找ID編號為2的人 //2-->ID屬性——OR——>SQL的Where語句 Person p = (Person)session.Get(typeof(Person), int.Parse(this.txtID.Text)); //Console.WriteLine(p.ToString()); this.txtName.Text = p.Name; } //刪除使用者 private void btnDelete_Click(object sender, EventArgs e) { try { //開啟事務 trans = session.BeginTransaction(); //根據提供的ID尋找該對象 Person p = (Person)session.Get(typeof(Person), int.Parse(this.txtID.Text)); //對象刪除 session.Delete(p); trans.Commit(); } catch (Exception) { trans.Rollback(); } } //更新使用者 private void btnUp_Click(object sender, EventArgs e) { try { //開啟事務 trans = session.BeginTransaction(); //根據提供的ID尋找該對象 Person p = (Person)session.Get(typeof(Person), int.Parse(this.txtID.Text)); //修改對象屬性 p.Name = this.txtName.Text; session.Update(p); trans.Commit(); } catch (Exception) { trans.Rollback(); } } //IQuery介面,是針對物件查詢 private void btnHQL_Click(object sender, EventArgs e) { //HQL體驗——HQL是針對對象的查詢語言 //查詢所有人的資訊 //IQuery query = session.CreateQuery("from Person"); //IList<Person> persons = query.List<Person>(); //persons.p1(); //查詢編號為2的人的資訊 //IQuery query = session.CreateQuery("from Person where Id=3"); //query.List<Person>().p1(); //查詢名字中有字母a的人 //session.CreateQuery("from Person where Name like '%a%'").List<Person>().p1(); //session.CreateQuery("from Person where t_Name like '%a%'").List<Person>().p1(); //session.CreateQuery("from Person where name like '%a%'").List<Person>().p1();//錯誤 //尋找全部 //session.CreateQuery("select p from Person p").List<Person>().p1(); //session.CreateQuery("select * from Person ").List<Person>().p1();//錯誤,沒有* //尋找編號大於5的人的資訊 //session.CreateQuery("from Person p where p.Id>5 ").List<Person>().p1(); //彙總函式的使用--統計人數 //session.CreateQuery("select count(p.Id) from Person p ").List().p2(); //傳參1 //IQuery query = session.CreateQuery("from Person p where p.Id>?"); //query.SetParameter(0,7); //query.List<Person>().p1(); //傳參2 //IQuery query = session.CreateQuery("from Person p where p.Id>:id"); //query.SetParameter("id", 7); //query.List<Person>().p1(); //插入資料——Insert/Update/Delete不建議在HQL裡面操作 //IQuery query = session.CreateQuery("insert into t_Person(t_Name) values(?)"); //query.SetParameter(0,"kkk"); //query.ExecuteUpdate(); //查詢指定範圍的資料——查詢第3-7條記錄 IQuery query = session.CreateQuery("from Person"); query.List<Person>().Skip<Person>(3).Take<Person>(5).ToList<Person>(); ; //用ICriteria來實現該功能可能更方便 } //對IList<Person>類型資料的輸出,建議用C#3.0的拓展方法來實現 public static class ExtraClass { public static void p1(this IList<Person> p) { //擷取可枚舉的介面對象 IEnumerator<Person> ie = p.GetEnumerator(); Console.WriteLine("\n-----------------------\n"); //遍曆 while (ie.MoveNext()) { Console.WriteLine(ie.Current.ToString()); } Console.WriteLine("\n-----------------------\n"); } public static void p2(this IList p) { IEnumerator ie = p.GetEnumerator(); Console.WriteLine("\n-----------------------\n"); while (ie.MoveNext()) { Console.WriteLine(ie.Current.ToString()); } Console.WriteLine("\n-----------------------\n"); } } }}
總結:對於NHibernate的操作,本文通過五部曲進行細緻的講解:1、建立表;2、建立類;3、建立對應檔(表和類是如何對應的);4、NH設定檔(串連資料庫);5、利用API操作。
其中,2、3 我們採用CodeSmith自動產生映射類和對應檔;4就是我們曾做的串連資料庫操作;5通過NHibernate提供的API,通過對對象操作,已達到操作資料庫的目的,避免了冗長複雜的sql語句。
希望大家重點理解建立的過程,以及API的使用。