将对象集合作为参数传递到SQL Server存储过程

wot*_*ney 3 sql vb.net sql-server asp.net stored-procedures

我有一个关于是否可以做某事的一般性问题 - 以及它是否是最有效的方式!

总结一下:我可以将对象集合作为参数传递给存储过程吗?

假设我有一个SQL Server表调用Users [UserID, Forename, Surname] ,另一个表调用Hobbies [HobbyID, UserID, HobbyName, HobbyTypeID]

此设置用于记录针对用户的多个爱好.

在我的应用程序中,我想更新用户记录.

通常 - 我会更新用户表,然后在代码中循环遍历每个爱好并按记录更新爱好表记录.

如果我正在更新用户的名字和2个他们的爱好,这将需要3次调用数据库.

(1调用存储过程来更新forename/surname,2调用存储过程来更新2个hobby记录)

我的问题是:
我可以通过将所有参数传递给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) 
    }
Run Code Online (Sandbox Code Playgroud)

我可以这样做吗?(哪种方式更有效?)存储过程会是什么样的?

ALTER PROCEDURE [dbo].[User_Update]

 @UserID    INT
,@Forename      NVARCHAR(50) = NULL
,@Surname   NVARCHAR(50) = NULL
,@Hobbies   ??????????????
Run Code Online (Sandbox Code Playgroud)

Aar*_*and 11

假设SQL Server 2008+,您可以使用表值参数执行此操作.首先在SQL Server中创建一个表类型:

CREATE TYPE dbo.HobbiesTVP AS TABLE
(
  HobbyID INT PRIMARY KEY,
  HobbyName NVARCHAR(50),
  HobbyTypeID INT
);
Run Code Online (Sandbox Code Playgroud)

然后你的存储过程会说:

@Hobbies dbo.HobbiesTVP READONLY
Run Code Online (Sandbox Code Playgroud)

在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()
}
Run Code Online (Sandbox Code Playgroud)