上兩篇,介紹使用MyGeneration提供的模板建立存儲過程和刪除對象、建立對象、更新對象整個詳細過程,這篇介紹如何利用<sql-query>作更多的事,在程序開發中,咱們不單單隻利用存儲過程增刪查改對象,咱們還能夠想執行任意的存儲過程,這不侷限於某個對象,某個CURD操做,怎麼作呢?注意:本篇並不是官方權威的資料,因此敬請參考。若是你尚未學習NHibernate,請快速連接到NHibernate之旅系列文章導航。html
下面我用幾個例子來分析使用<sql-query>來執行存儲過程。sql
Step1:存儲過程session
CREATE PROCEDURE scalarSProcs @number int AS BEGIN SELECT @number as value, 'YJingLee' as name END
這裏模擬驗證鍵/值對,按鍵查詢名稱。這裏返回YJingLee。學習
Step2:映射文件測試
在映射文件中使用<sql-query>並定義<sql-query>查詢的名稱,使用<return-scalar>元素來指定返回的標量值,並指定字段的別名和類型。調用存儲過程時,須要一個參數,這裏用命名參數表示,這裏打開Customer.hbm.xml在Class元素上編寫以下代碼:spa
<sql-query name="ScalarSProcs"> <return-scalar column="value" type="int"/> <return-scalar column="name" type="string"/> exec scalarSProcs :number </sql-query>
Step3:數據訪問方法scala
在數據訪問層中,使用ISession接口提供的GetNamedQuery方法來調用帶命名的存儲過程,並傳遞一個整形參數。代碼以下:code
public IList ScalarStoredProcedure() { return _session.GetNamedQuery("ScalarSProcs") .SetInt32("number", 22).List(); }
Step4:測試方法xml
測試上面的方法,驗證其標量返回的結果是否與預期的一致。htm
[Test] public void ScalarStoredProcedureTest() { IList list = _sprocs.ScalarStoredProcedure(); object[] o = (object[])list[0]; Assert.AreEqual(o[0], 22); Assert.AreEqual(o[1], "YJingLee"); }
OK,測試成功,NHibernate生成SQL語句以下:
exec scalarSProcs @p0; @p0 = '22'
Step1:存儲過程
CREATE PROCEDURE paramSProcs @i int, @j int AS BEGIN SELECT @i as value, @j as value2 END
這裏模擬一個存儲過程,學習如何運用參數。
Step2:映射文件
帶參數的存儲過程,參數有兩種寫法,一種是使用「?」參數來表示:
<sql-query name="ParamSProcs"> <return-scalar column="value" type="long"/> <return-scalar column="value2" type="long"/> exec paramSProcs ?, ? </sql-query>
另一種是混合方式,使用「?」參數和命名參數表示:
<sql-query name="ParamSProcs"> <return-scalar column="value" type="long" /> <return-scalar column="value2" type="long" /> exec paramSProcs ?, :second </sql-query>
Step3:數據訪問方法
在數據訪問層中,咱們一樣使用GetNamedQuery方法來調用命名的<sql-query>存儲過程,須要傳遞兩個參數,這裏支持位置參數和命名參數,其方法以下所示:
public IList ParamStoredProcedure() { return _session.GetNamedQuery("ParamSProcs") .SetInt64(0, 10L) .SetInt64(1, 20L) //或者.SetInt64("second", 20L) .List(); }
Step4:測試方法
編寫一個測試用例測試上面的方法,OK!
[Test] public void ParamStoredProcedureTest() { IList list = _sprocs.ParamStoredProcedure(); object[] o = (object[])list[0]; Assert.AreEqual(o[0], 10L); Assert.AreEqual(o[1], 20L); }
Step1:存儲過程
上面的查詢都是返回標量值的,也就是返回是的「裸」數據。 我須要查詢Customer實體對象,怎麼辦呢?編寫一個存儲過程按CustomerId查詢Customer。
CREATE PROCEDURE [entitySProcs] @CustomerId int AS BEGIN SELECT * FROM [Customer] WHere [CustomerId] =@CustomerId END
Step2:映射文件
經過命名查詢來映射這個存儲過程,使用return返回具體的實體類,使用<return-property>告訴NHibernate使用哪些屬性值,容許咱們來選擇如何引用字段以及屬性。
<sql-query name="EntitySProcs"> <return class="DomainModel.Entities.Customer,DomainModel"> <return-property name="CustomerId" column="CustomerId"/> <return-property name ="Version" column="Version"/> <return-property name="Firstname" column="Firstname"/> <return-property name="Lastname" column="Lastname"/> </return> exec entitySProcs :customerId </sql-query>
這很是奇怪,我使用這種方式測試不經過,晚上和Gray Zhang討論這個問題,Gray Zhang使用這個方式運行成功,在個人機器上運行不成功,始終出現「NHibernate.ADOException : could not execute query [ exec entitySProcs ? ] Name:customerId - Value:1 [SQL: exec entitySProcs ?] 」問題,我換了一下方式,去掉<return-property>元素,像這樣:
<sql-query name="EntitySProcs"> <return class="DomainModel.Entities.Customer,DomainModel"/> exec entitySProcs :customerId </sql-query>
Step3:數據訪問方法
public Customer EntityStoredProcedure(int customerId) { return _session.GetNamedQuery("EntitySProcs") .SetInt32("customerId",customerId) .UniqueResult<Customer>(); }
Step4:測試方法
[Test] public void EntityStoredProcedureTest() { Customer customer = _sprocs.EntityStoredProcedure(1); int customerId = customer.CustomerId; Assert.AreEqual(1, customerId); }
Step5:返回實體屬性
有個需求,我不想返回整個實體Customer,我想返回實體的Firstname屬性怎麼辦呢?哦,反應過來了,使用返回標量的方法,我來寫下<sql-query>:
<sql-query name="SingleEntitySProcs"> <return-scalar column="Firstname" type="string" /> exec singleEntitySProcs </sql-query>
注意存儲過程當前僅僅返回標量和實體。接下來就留給你們完成吧!給個提示,先寫存儲過程,而後寫訪問方法,最後測試一下看看是否返回的Firstname列表了。
使用存儲過程查詢沒法使用setFirstResult()/setMaxResults()進行分頁。
存儲過程的參數的位置順序是很是重要,必須和NHibernate持久化類屬性順序相同。
你能夠在存儲過程裏設定SET NOCOUNT ON,這可能會提升效率。
咱們能夠在類映射裏使用<loader query-ref="EntitySProcs"/>引用這個命名查詢定製裝載存儲過程。
好了,經過三篇文章的介紹,知道了如何在NHibernate使用存儲過程來刪除對象、建立對象、更新對象、查詢對象等操做,還有一些零碎的東西就在於你們在平時學習中去探索了。NHibernate之旅系列中關於存儲過程的內容就說到這裏吧,下篇開始看看如何使用代碼生成器。
本系列連接:NHibernate之旅系列文章導航
下次繼續分享NHibernate!