【问题标题】:Passing an object collection as a parameter into SQL Server stored procedure将对象集合作为参数传递到 SQL Server 存储过程
【发布时间】:2012-07-11 13:17:31
【问题描述】:

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

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

假设我有一个名为 Users [UserID, Forename, Surname] 的 SQL Server 表 和另一个名为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   ??????????????

【问题讨论】:

  • 您使用的是什么版本的 SQL Server?

标签: asp.net sql sql-server vb.net stored-procedures


【解决方案1】:

假设 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()
}

【讨论】:

  • 我不确定您是否可以将任意集合作为表值参数传递。 MSDN 文档谈到了实现 DataReader 接口的 DataTable 或对象。本文也采用了不同的方法。blogs.inkeysolutions.com/2011/04/…
  • @Steve 好的,那么集合可能需要是 ListDataTable。我没有明确尝试过,我只使用了DataTable,但我希望一个集合是兼容的。
  • 我们使用集合而不是数据表来做到这一点。主要是它绕过了在推入 TVP 之前将现有集合转换为数据表的需要:lennilobel.wordpress.com/2009/07/29/…
  • 非常感谢大家,我会考虑让这个工作。没有人评论哪种方法最有效 - 有什么想法吗?
  • @wotney 你的意思是 DataTable 和集合之间哪个更有效?如果是这样,我不知道,我从来没有从 C# 方面分析过那些。如果它们都处理 TVP,那么我必须假设最大的瓶颈(数据库)是不变的,并且它们在 C# 中的任何差异都可以忽略不计。
猜你喜欢
  • 2017-03-18
  • 1970-01-01
  • 2016-09-25
  • 1970-01-01
  • 2014-07-30
  • 2014-09-29
  • 1970-01-01
  • 1970-01-01
  • 2015-12-20
相关资源
最近更新 更多