[NHibernate]存儲過程的使用(一)


目錄

寫在前面

文檔與系列文章

Nhibernate中使用存儲過程

一個例子

總結

寫在前面

上篇文章一個小插曲,分析了延遲加載是如何解決N+1 select查詢問題的。這篇開始介紹在nhibernate中如何使用存儲過程,同時也介紹如何使用代碼生成器,提高開發效率。

文檔與系列文章

[Nhibernate]體系結構

[NHibernate]ISessionFactory配置

[NHibernate]持久化類(Persistent Classes)

[NHibernate]O/R Mapping基礎

[NHibernate]集合類(Collections)映射 

[NHibernate]關聯映射

[NHibernate]Parent/Child

[NHibernate]緩存(NHibernate.Caches)

[NHibernate]NHibernate.Tool.hbm2net

[NHibernate]Nullables

[NHibernate]Nhibernate如何映射sqlserver中image字段

[NHibernate]基本配置與測試 

[NHibernate]HQL查詢 

[NHibernate]條件查詢Criteria Query

[NHibernate]增刪改操作

[NHibernate]事務

[NHibernate]並發控制

[NHibernate]組件之依賴對象

[NHibernate]一對多關系(級聯刪除,級聯添加)

[NHibernate]一對多關系(關聯查詢)

[NHibernate]多對多關系(關聯查詢)

[NHibernate]延遲加載

[NHibernate]立即加載

[NHibernate]視圖處理

[NHibernate]N+1 Select查詢問題分析

Nhibernate中使用存儲過程

這里使用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_procs_TB_Customer.sql

我使用的是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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM