NHibernate Step by Step (五)Criteria Query
可能很多人象我一樣,剛開始接觸HQL時,腦袋一片混沌,這是什麼語法嘛!!之所以這樣,是因爲我們總是會先入爲主地將之與SQL想比,雖然HQL看起來很SQL,而且設計時就有這樣的意圖,但是畢竟是兩種差別很大的東西,難免就會出現理解偏差的問題。好了,我們今天就不讓大家腦袋發暈了,HQL我們暫時放一放。今天我們來說另外一種查詢方法:
Criteria Query.
什麼是Criteria Query?簡單說,就是將我們的查詢條件封裝爲一個預定義的查詢對象,由這個查詢對象來執行查詢,而不用我們再去寫HQL了,而且更接近我們貫常的編程習慣。
是不是很不錯?讓我們來look look:
//創建關聯到某個類的查詢對象
ICriteria criteria = session.CreateCriteria(typeof(Person));
//添加表達式
criteria.Add(Expression.Eq("Name","Jackie Chan"));
IList list = criteria.List();
注意這一句:
Expression.Eq("Name","Jackie Chan")
Eq是Equal的縮寫,意思是添加一個查詢表達式,Person.Name = “Jackie Chan”
對應HQL就是:
from Person p where p.Name=”Jackie Chan”
NHibernate會在運行時動態生成類似上面的HQL,我們可以在配置文件把show-sql打開,觀看生成的SQL。
這樣是不是感覺清晰多了?又回到我們以前的編碼習慣了!
爲了對應HQL的種種查詢條件,NHibernate預定義了大量的Expression方法,我們列幾個如下:
Eq = Equal
Gt = Greater than
Lt = Less than
Like = Like
Not = Not
IsNull = Is Null
基本上對應了大部分
HQL的語義,詳細的說明請參考api。
下面,我們詳細介紹Criteria的用法。
1. Example查詢
我們常常有這樣的查詢頁面:
用戶可以輸入“姓名”、“性別”、“年齡”等等來進行查詢,而我們常常的做法就是如下的煩瑣:
string condition = “”;
if(txtName.Text != null)
condition += “ Name=” + txtName.Text;
if(txtSex.Text != null)
condition += “ and Sex=” + txtSex.Text;
……
代碼看起來實在是不甚美觀,有什麼解決辦法呢?
Criteria提供了專爲這種問題而設計的Example查詢,如下:
ICriteria criteria = session.CreateCriteria(typeof(Person));
Person person = new Person();
person.Name = "Jackie Chan";
person.Age = 50;
//創建一個Example對象
criteria.Add(Example.Create(person));
IList list = criteria.List();
請注意:
criteria.Add(Example.Create(person));
這句代碼的意思是通過構造的person對象的屬性來生成表達式,實際生成的代碼如下:
SELECT this.id as id0_, this.name as name0_, this.age as age0_ FROM Person this WHERE (this.age = @p0)
對應上面的問題,我們簡單地new出一個person對象,然後填充其屬性即可,不用再去構造那醜陋的條件判斷語句了!
2. 排序
我們想對返回的list進行排序,該怎麼辦呢?如下:
ICriteria criteria = session.CreateCriteria(typeof(Person));
criteria.Add(Expression.Gt("Age", 20));
//添加一個排序對象
criteria.AddOrder(Order.Asc("Age"));
IList list = criteria.List();
請注意:
criteria.AddOrder(Order.Asc("Age"));
這句代碼的意思是在criteria上構造一個排序對象,並以Age屬性做正序排列,NHibernate在運行時會生成如下語句:
SELECT this.id as id0_, this.name as name0_, this.age as age0_ FROM Person this WHERE this.age > @p0 ORDER BY this.age asc
如你所猜想,Order類肯定有另外一個“Desc“方法:)
3. 限制記錄範圍
在顯示大量的記錄時,我們常常採用的方法就是分頁,如果用NHibernate來做,該怎麼辦呢?
如下代碼:
ICriteria criteria = session.CreateCriteria(typeof(Person));
//從第10條記錄開始取
criteria.SetFirstResult(10);
//取20條記錄
criteria.SetMaxResults(20);
IList list = criteria.List();
這樣,我們就達到了分頁的目的。
注意:
NHibernate的分頁機制實際上依賴於不同的數據庫實現,所以,對特定的某種數據庫,並不一定是效率最好的,比如對SQLServer(爲什麼受傷的總是俺?爲什麼總是說俺比不上Oracle?俺都趕在2005年年底出2005版本了!!)。想知道爲什麼嗎?很簡單,check一下上面代碼生成的SQL就清楚了!或者深入點再看看NHibernate的分頁代碼,我就不解釋了,自己動手,豐衣足食:)
總體來講,Criteria對我們來說更熟悉,更容易上手,但是目前Criteria還是不夠完善——將對應的HQL一一封裝實在太煩瑣了,所以NHibernate還是以HQL查詢爲主,我們在使用的時候則看需要了,要麼使用HQL,要麼HQL和Criteria混合使用,重要的是解決問題,對不?
[TestMethod]
public void CriteriaExample()
{
Person per = new Person();
per.Id = 4;
ICriteria criteria = session.CreateCriteria(typeof(Person));
criteria.Add(Example.Create(per));
IList list = criteria.List();
Assert.AreNotEqual(0,list.Count, "fail");
}
請問哪寫錯了? 回覆 引用 查看
Example.create:Version properties, identifiers and associations are ignored. By default, null valued properties are excluded. 回覆 引用 查看
是不是我上面寫的方法轉換成HQL之後並不只是ID這一個參數?
如果是的話,怎麼樣才能達到我想要的效果呢? 回覆 引用 查看
我的是在你第一篇文章中的地址下載的 回覆 引用 查看
1.SELECT this.id as id0_, this.name as name0_, this.age as age0_ FROM Person this WHERE (this.age = @p0)應該是
SELECT this.id as id0_, this.age as age0_, this.name as name0_ FROM Person this WHERE (this.age = @p0 and this.name = @p1)
2.//從第10條記錄開始取
criteria.SetFirstResult(10);
這裏不應該是說從第10條開始,而就是第11條,
criteria.SetFirstResult(9);纔是第10條.NHibernate中是從0開始計數的.
回覆 引用 查看
不勝感激.... 回覆 引用 查看
[引用提示]大冰引用了該文章, 地址: http://www.cnblogs.com/hanbing768/archive/2007/07/15/818697.html 回覆 引用 查看
[引用提示]MichaeL引用了該文章, 地址: http://www.cnblogs.com/MichaelLu/archive/2007/07/24/829714.html 回覆 引用 查看