2012-07-11 153 views
1

對於是否可以完成某些操作,以及它是否是最有效的方法,我有一個普遍的問題!將對象集合作爲參數傳遞到SQL Server存儲過程

總結:可以將對象集合作爲參數傳遞給存儲過程嗎?

比方說,我有一個SQL Server表稱爲Users [UserID, Forename, Surname] 和另一個表稱爲Hobbies [HobbyID, UserID, HobbyName, HobbyTypeID]

此設置是打擊用戶記錄多個愛好。

在我的應用程序中,我想更新用戶記錄。

通常情況下 - 我會更新用戶表,然後在代碼中循環遍歷每個愛好並通過記錄更新愛好表記錄。

如果我正在更新用戶名和他們的愛好2,這將需要3次調用數據庫。

(1調用存儲過程來更新用的名字/姓氏和2個調用存儲過程來更新2嗜好記錄)

我的問題是:
我可以做只是1調用數據庫通過將所有參數傳遞給1個存儲過程。

例如。

intUserID = 1 
strForename = "Edward" 
strSurname = "ScissorHands" 

dim objHobbyCollection as New List(Of Hobby) 
'Assume that I have 2 hobby objects, each with their hobbyID, UserID, HobbyName & HobbyTypeID 

Dim params As SqlParameter() 
params = New SqlParameter() { 
    New SqlParameter("@UserID", intUserID), 
    New SqlParameter("@Forename", strForename), 
    New SqlParameter("@Surname", strSurname), 
    New SqlParameter("@Hobbies", objHobbyCollection) 
    } 

我可以這樣做嗎? (哪種方式會更有效?) 存儲過程的外觀如何?

ALTER PROCEDURE [dbo].[User_Update] 

@UserID INT 
,@Forename  NVARCHAR(50) = NULL 
,@Surname NVARCHAR(50) = NULL 
,@Hobbies ?????????????? 
+1

你正在使用什麼版本的SQL Server? – 2012-07-11 20:24:06

+0

SQL Server 2008 R2 – wotney 2012-07-12 16:36:26

回答

8

假設SQL Server 2008+,您可以使用表值參數來執行此操作。首先在SQL Server中創建一個表類型:

CREATE TYPE dbo.HobbiesTVP AS TABLE 
(
    HobbyID INT PRIMARY KEY, 
    HobbyName NVARCHAR(50), 
    HobbyTypeID INT 
); 

那麼你的存儲過程會說:

@Hobbies dbo.HobbiesTVP READONLY 

在C#(對不起,我不知道vb.net當量)這將是如下(但是如果你只有一個UserID,這不需要成爲集合的一部分,是嗎?):

// as Steve pointed out, you may need to have your hobbies in a DataTable. 

DataTable HobbyDataTable = new DataTable(); 
HobbyDataTable.Columns.Add(new DataColumn("HobbyID")); 
HobbyDataTable.Columns.Add(new DataColumn("HobbyName")); 
HobbyDataTable.Columns.Add(new DataColumn("HobbyTypeID")); 

// loop through objHobbyCollection and add the values to the DataTable, 
// or just populate this DataTable in the first place 

using (connObject) 
{ 
    SqlCommand cmd = new SqlCommand("dbo.User_Update", connObject); 
    cmd.CommandType = CommandType.StoredProcedure; 
    // other params, e.g. @UserID 
    SqlParameter tvparam = cmd.Parameters.AddWithValue("@Hobbies", HobbyDataTable); 
    tvparam.SqlDbType = SqlDbType.Structured; 
    // ...presumably ExecuteNonQuery() 
} 
+0

我不確定您是否可以將任意集合作爲表值參數傳遞。 MSDN文檔討論DataTable或實現DataReader接口的對象。另外這篇文章遵循不同的方法.http://blogs.inkeysolutions.com/2011/04/pass-collection-of-object-as-table.html – Steve 2012-07-11 20:40:31

+0

@Steve ok,那麼集合可能需要是一個List '或'DataTable'。我沒有明確地嘗試過,我只使用了'DataTable',但我期望集合是兼容的。 – 2012-07-11 20:41:26

+0

我們用集合來代替數據表。它主要是繞過了在推入TVP之前將現有集合轉換爲數據表的需求:http://lennilobel.wordpress.com/2009/07/29/sql-server-2008-table-valued-parameters-and-c-定製迭代器-a-match-made-in-heaven/ – NotMe 2012-07-11 20:57:14

相關問題