寫在前面html
文檔與系列文章sql
一個例子緩存
總結session
上篇文章一個小插曲,分析了延遲加載是如何解決N+1 select查詢問題的。這篇開始介紹在nhibernate中如何使用存儲過程,同時也介紹如何使用代碼生成器,提升開發效率。併發
[NHibernate]ISessionFactory配置ide
[NHibernate]持久化類(Persistent Classes)函數
[NHibernate]O/R Mapping基礎sqlserver
[NHibernate]集合類(Collections)映射
[NHibernate]緩存(NHibernate.Caches)
[NHibernate]NHibernate.Tool.hbm2net
[NHibernate]Nhibernate如何映射sqlserver中image字段
[NHibernate]條件查詢Criteria Query
這裏使用MyGeneration Code來生成針對TB_Customer數據表的增刪改的存儲過程。MyGeneration Code是一款開源的代碼生成器,下載地址MyGeneration Code。
安裝完成後,打開MyGeneration,若是第一次使用MyGeneration會自動彈出「默認設置」對話框,須要你對MyGeneration設置數據庫鏈接字符串、模板語言、數據庫驅動、模板存放路徑等信息。
而後選擇「save」對默認配置進行保存。而後MyGenration主界面就會彈出。如圖
展開Microsoft SQL Server節點,找到「Script Insert/Update/Delete Procedures for SQL Server」模板,右擊選擇執行,咱們利用這個模板爲Customer表生成增刪改存儲過程。
打開後,這個模板界面以下,選擇輸出路徑和數據庫表,這裏我輸入路徑爲桌面,選擇TB_Customer表,點擊OK。截圖以下:
此時在桌面「C:\Users\Wolfy\Desktop\Customer」中就會生成sql_procs_TB_Customer.sql文件,打開數據庫,而後執行該文件中的sql腳本。
1 USE [Shop] 2 GO 3 4 --|-------------------------------------------------------------------------------- 5 --| [TB_CustomerInsert] - Insert Procedure Script for TB_Customer 6 --|-------------------------------------------------------------------------------- 7 IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id (N'[dbo].[TB_CustomerInsert]') AND OBJECTPROPERTY(id, N'IsProcedure') = 1) DROP PROCEDURE [dbo].[TB_CustomerInsert] 8 GO 9 10 CREATE PROCEDURE [dbo].[TB_CustomerInsert] 11 ( 12 @CustomerID uniqueidentifier = NEWID() OUTPUT, 13 @CustomerName nvarchar(16) = NULL, 14 @CustomerAddress nvarchar(128) = NULL, 15 @Version int 16 ) 17 AS 18 SET NOCOUNT ON 19 20 INSERT INTO [TB_Customer] 21 ( 22 [CustomerID], 23 [CustomerName], 24 [CustomerAddress], 25 [Version] 26 ) 27 VALUES 28 ( 29 @CustomerID, 30 @CustomerName, 31 @CustomerAddress, 32 @Version 33 ) 34 35 RETURN @@Error 36 GO 37 38 --|-------------------------------------------------------------------------------- 39 --| [TB_CustomerUpdate] - Update Procedure Script for TB_Customer 40 --|-------------------------------------------------------------------------------- 41 IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id (N'[dbo].[TB_CustomerUpdate]') AND OBJECTPROPERTY(id, N'IsProcedure') = 1) DROP PROCEDURE [dbo].[TB_CustomerUpdate] 42 GO 43 44 CREATE PROCEDURE [dbo].[TB_CustomerUpdate] 45 ( 46 @CustomerID uniqueidentifier, 47 @CustomerName nvarchar(16) = NULL, 48 @CustomerAddress nvarchar(128) = NULL, 49 @Version int 50 ) 51 AS 52 SET NOCOUNT ON 53 54 UPDATE [TB_Customer] 55 SET 56 [CustomerID] = @CustomerID, 57 [CustomerName] = @CustomerName, 58 [CustomerAddress] = @CustomerAddress, 59 [Version] = @Version 60 WHERE 61 [CustomerID] = @CustomerID 62 63 RETURN @@Error 64 GO 65 66 --|-------------------------------------------------------------------------------- 67 --| [TB_CustomerDelete] - Update Procedure Script for TB_Customer 68 --|-------------------------------------------------------------------------------- 69 IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id (N'[dbo].[TB_CustomerDelete]') AND OBJECTPROPERTY(id, N'IsProcedure') = 1) DROP PROCEDURE [dbo].[TB_CustomerDelete] 70 GO 71 72 CREATE PROCEDURE [dbo].[TB_CustomerDelete] 73 ( 74 @CustomerID uniqueidentifier 75 ) 76 AS 77 SET NOCOUNT ON 78 79 DELETE 80 FROM [TB_Customer] 81 WHERE 82 [CustomerID] = @CustomerID 83 84 RETURN @@Error 85 GO
我使用的是sql server2012的版本,在執行腳本的時候,生成添加Customer的存儲過程,有問題
將NewId()函數去掉。修改後的存儲過程
1 USE [Shop] 2 GO 3 --|-------------------------------------------------------------------------------- 4 --| [TB_CustomerInsert] - Insert Procedure Script for TB_Customer 5 --|-------------------------------------------------------------------------------- 6 IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id (N'[dbo].[TB_CustomerInsert]') AND OBJECTPROPERTY(id, N'IsProcedure') = 1) DROP PROCEDURE [dbo].[TB_CustomerInsert] 7 GO 8 9 CREATE PROCEDURE [dbo].[TB_CustomerInsert] 10 ( 11 @CustomerID uniqueidentifier OUTPUT, 12 @CustomerName nvarchar(16) = NULL, 13 @CustomerAddress nvarchar(128) = NULL, 14 @Version int 15 ) 16 AS 17 SET NOCOUNT ON 18 19 INSERT INTO [TB_Customer] 20 ( 21 [CustomerID], 22 [CustomerName], 23 [CustomerAddress], 24 [Version] 25 ) 26 VALUES 27 ( 28 NEWID(), 29 @CustomerName, 30 @CustomerAddress, 31 @Version 32 ) 33 34 RETURN @@Error
生成的存儲過程以下:
在NHibernate的映射文件中,在Class元素中提供了<sql-delete>、<sql-insert>、<sql-update>元素用於刪除、新建、更新對象,注意這三個元素順序惟一,就是下圖顯示的順序,在根元素提供了<sql-query>元素用來查詢對象,下圖顯示在Class元素中的增刪改存儲過程元素。
刪除對象
修改映射文件添加存儲過程,打開Customer.hbm.xml映射文件,在Class元素下添加<sql-delete>節點,調用TB_CustomerDelete存儲過程,TB_CustomerDelete存儲過程有一個CustomerID參數,這裏用一個問號表示:
<!--存儲過程,check參數:none/rowcount/param--> <sql-delete>exec TB_CustomerDelete ?</sql-delete>
測試
1 /// <summary> 2 /// 經過存儲過程方式刪除客戶信息 3 /// </summary> 4 /// <param name="customer"></param> 5 /// <returns></returns> 6 public bool DeleteCustomerByIDWithProcedure(Customer customer) 7 { 8 var session = NHibernateHelper.GetSession(); 9 using (ITransaction trans = session.BeginTransaction()) 10 { 11 try 12 { 13 session.Delete(customer); 14 session.Flush(); 15 trans.Commit(); 16 return true; 17 } 18 catch (Exception) 19 { 20 trans.Rollback(); 21 throw; 22 } 23 } 24 }
此時會有一個異常「Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [Wolfy.Shop.Domain.Entities.Customer#b0720295-9541-40b3-9994-610066224db8]」。這個錯誤是存儲過程寫法錯誤,咱們修改TB_CustomerDelete存儲過程,去掉SET NOCOUNT ON,代碼片斷以下:
1 ALTER PROCEDURE [dbo].[TB_CustomerDelete] 2 ( 3 @CustomerID uniqueidentifier 4 ) 5 AS 6 --SET NOCOUNT ON 7 8 DELETE 9 FROM [TB_Customer] 10 WHERE 11 [CustomerID] = @CustomerID 12 13 RETURN @@Error
再次運行進行測試,測試成功,查看生成的sql語句
你會發如今sql語句裏面多了一個@p1的參數。這個參數爲以前添加的Version參數,nhibernate中樂觀併發控制添加的。
如何解決?
修改存儲過程,將版本號添加上。
1 ALTER PROCEDURE [dbo].[TB_CustomerDelete] 2 ( 3 @CustomerID uniqueidentifier, 4 @Version int 5 ) 6 AS 7 --SET NOCOUNT ON 8 9 DELETE 10 FROM [TB_Customer] 11 WHERE 12 [CustomerID] = @CustomerID and [Version]=@Version 13 14 RETURN @@Error
不要忘了,此時的存儲過程有兩個參數了,版本號在映射文件中已經處理了,存儲過程當中已經幫我們自動添加上了,若是是其餘的參數可在映射文件經過"?,?..."添加多個參數。
<!--存儲過程,check參數:none/rowcount/param--> <sql-delete check="rowcount" >exec TB_CustomerDelete ?</sql-delete>
再次運行進行測試,成功,生成的sql語句
exec sp_executesql N'exec TB_CustomerDelete @p0',N'@p0 uniqueidentifier,@p1 int',@p0='3727A133-C079-4DF9-B31E-7625B03F95DF',@p1=1
固然了,若是你不想使用存儲過程,也能夠直接在<sql-delete>中寫SQL語句,像這樣,照樣用。
<sql-delete>DELETE FROM [TB_Customer] WHERE [CustomerID] = ? and [Version] =?</sql-delete>
生成的sql語句爲
exec sp_executesql N'DELETE FROM [TB_Customer] WHERE [CustomerID] = @p0 and [Version] =@p1',N'@p0 uniqueidentifier,@p1 int',@p0='64C35DEE-84D9-4C2D-ABAF-7D53631E3EAA',@p1=1
這篇文章主要介紹了代碼生成器的簡單使用及nhibernate中使用存儲過程刪除數據的過程。
參考文章:http://www.cnblogs.com/lyj/archive/2008/11/03/1325291.html