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)