如何在C#中将DataTable作为Paramter tp存储过程传递?

时间:2015-07-08 10:49:23

标签: c# sql asp.net c#-4.0

我创建了User-Defined Table Type并编写了存储过程,如下所示:

//Create the data type
CREATE TYPE [dbo].tbl_admintype AS TABLE 
(
    [code] [varchar](50) NULL,
    [name] [varchar](100) NULL,
    [branch] [varchar](100) NULL default '',
    [location] [varchar](100) NULL default '',
    [usertype] [varchar](50) NULL,
    [password] [varchar](max) NULL,
    [saltkey] [varchar](100) NULL
)
GO

//Stored Procedure
create PROCEDURE [dbo].[proc_tbl_admin_InsertItem]
    @tbl_admintype tbl_admintype READONLY
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    MERGE INTO tbl_admin a
    USING @tbl_admintype at
    ON a.code=at.code and a.usertype=at.usertype
    --WHEN MATCHED THEN
        --UPDATE SET a.Name = at.Name,a.Country = at.Country
    WHEN NOT MATCHED THEN
        INSERT VALUES(at.name, at.code, at.password, at.saltkey,at.branch,at.location,at.usertype,1,getdate(),getdate());

    select ''
END

以下代码可以正常工作:

using (SqlConnection con1 = new SqlConnection(connectionstring))
{
    using (SqlCommand cmd1 = new SqlCommand("proc_tbl_admin_InsertItem"))
        {
            cmd1.CommandType = CommandType.StoredProcedure;
            cmd1.Connection = con1;                                               

            cmd1.Parameters.AddWithValue("@tbl_admintype", dt);
            con1.Open();
            cmd1.ExecuteNonQuery();
            con1.Close();
        }
}

但是当我使用以下功能时:

public int ExecuteNonQuery(string spName, params object[] parameterValues)
{
    try
    {

        return db.ExecuteNonQuery(spName, parameterValues);
    }
    catch (DALException ex)
    {
        throw ex;
    }
}

它给出了错误:

  

"传入的表格数据流(TDS)远程过程调用(RPC)   协议流不正确。表值参数1   (" @ tbl_admintype"),第0行,第0列:数据类型0xF3(用户定义)   table type)指定了一个非零长度的数据库名称。数据库   表值参数不允许使用name,只允许使用模式名称   和类型名称有效。"。

2 个答案:

答案 0 :(得分:0)

请勿使用AddWithValue。相反,这样做:

cmd1.Parameters.Add("@tbl_admintype", SqlDbType.Structured).Value = dt; 

如果您坚持使用AddWithValue,可以这样做:

SqlParameter tvpParam = cmb1.Parameters.AddWithValue(
"@tbl_admintype", dt);
tvpParam.SqlDbType = SqlDbType.Structured;

这可以完成,因为Add方法和AddWithValue方法都返回对参数的引用。

有关详细信息,请read this MSDN page.

答案 1 :(得分:0)

您应该在SQL Server上创建User Defined Table Type,以便将DataTable从C#发送到存储过程。

在SSMS中打开:

Programmability -> Types -> UserDefined Table Types并右键点击New -> UserDefinedTableType

然后:

USE [YourDatabase]
GO

/****** Object:  UserDefinedTableType [dbo].[tp_ParameterList]    
        Script Date: 18.10.2017 10:36:40 ******/
CREATE TYPE [dbo].[tp_ParameterList] AS TABLE(
    [Name] [VARCHAR](255) NULL,
    [Val] [VARCHAR](255) NULL
)
GO

现在,您可以使用可以接受DataTable的参数执行存储过程:

ALTER PROCEDURE [dbo].[YourSPWithDataTable](
     @AdditionalParams      dbo.tp_ParameterList READONLY
  )

AS

你可以从stored procedure那样打电话给C#

var cmd = new SqlCommand("YourSPWithDataTable", db.Database.Connection as SqlConnection,                                   
                 db.Database.CurrentTransaction.UnderlyingTransaction as SqlTransaction);
cmd.CommandType = CommandType.StoredProcedure;
DataTable dt = new DataTable();
dt.Columns.Add("Name");
dt.Columns.Add("Val");
dt.Rows.Add("id_Person", 1);
dt.Rows.Add("id_Dep", 1);
cmd.Parameters.Add(new SqlParameter("@AdditionalParams", dt));
cmd.ExecuteNonQuery();
相关问题