6

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

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

假设我有一个名为的 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   ??????????????
4

1 回答 1

12

假设 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 等效项)如下所示(但如果您只有一个用户 ID,则它不需要成为集合的一部分,对吗?):

// 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()
}
于 2012-07-11T20:26:38.150 回答