asp.net – SQL Server用户定义的表类型和.NET

我需要将一个整数数组从.NET传递给一个存储过程,所以我搜索了这个主题并最终跑过了
Arrays and Lists in SQL Server 2008,由Erland Sommarskog编写并且据称被认为是进行此过程的标准方式.

我已经尝试了两种不同的方式将用户定义的表类型传递给存储过程,但我每个都得到例外.这两种方式都与Erland Sommarskog在上面的链接中使用的方式类似.

方式#1 – 使用DataTable作为SqlParameter

DataTable dt = new DataTable();
dt.Columns.Add("n", typeof(int));

// Just adding 3 test rows to the DataTable
DataRow dr = dt.NewRow();
dr["n"] = 1;
dt.Rows.Add(dr);

dr = dt.NewRow();
dr["n"] = 2;
dt.Rows.Add(dr);

dr = dt.NewRow();
dr["n"] = 3;
dt.Rows.Add(dr);

// Creation of the SqlParameter
SqlParameter p = new SqlParameter();
p.ParameterName = "@ids";
p.Direction = ParameterDirection.Input;
p.SqlDbType = SqlDbType.Structured;
p.TypeName = "lstInt_TblType";
p.Value = dt;

// Blows up here
DataSet ds = DAWrapper.GetDataSet(
    Common.GetDB(),
    "usp_Test",
    new SqlParameter[] { p });

我得到的例外是:
传入的表格数据流(TDS)远程过程调用(RPC)协议流不正确.参数1(“@ids”):数据类型0x62(sql_variant)具有类型特定元数据的无效类型.

方式2 – 使用List作为SqlParameter

List<SqlDataRecord> lstSDR = new List<SqlDataRecord>();
SqlMetaData[] tvp_definition = { new SqlMetaData("n", SqlDbType.Int) };

// Just adding 3 test rows
SqlDataRecord rec = new SqlDataRecord(tvp_definition);
rec.SetInt32(0, 50);
lstSDR.Add(rec);

rec = new SqlDataRecord(tvp_definition);
rec.SetInt32(0, 51);
lstSDR.Add(rec);

rec = new SqlDataRecord(tvp_definition);
rec.SetInt32(0, 52);
lstSDR.Add(rec);

// Creation of the SqlParameter
SqlParameter p = new SqlParameter();
p.ParameterName = "@ids";
p.Direction = ParameterDirection.Input;
p.SqlDbType = SqlDbType.Structured;
p.TypeName = "lstInt_TblType";
p.Value = lstSDR;

// Blows up here
DataSet ds = DAWrapper.GetDataSet(
    Common.GetDB(),
    "usp_Test",
    new SqlParameter[] { p });

我得到的例外情况表明:
从对象类型System.Collections.Generic.List`1 [[Microsoft.SqlServer.Server.SqlDataRecord,System.Data,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089]]到目标托管提供程序本机不存在映射类型.

其他信息
lstInt_TblType是我的SQL Server 2008中用户定义的表类型.它确实存在(我对此进行了三重检查!).它有一个名为“n”的列,类型为int,主键,不允许空值.我复制了Erland如何设置他的.

我还验证了存储过程usp_Test可以在SQL Server Manager Studio中运行,因此我非常确定异常不会从该方向发出.这是我用来验证存储过程是否有效的t-sql:

DECLARE @ids lstInt_TblType
INSERT @ids(n) VALUES(1),(2),(3)
EXEC usp_Test ids

任何有关如何使用此建议的建议将不胜感激.谢谢!

*编辑:*
存储过程usp_Test:

ALTER PROCEDURE [dbo].[usp_Test]
(
    @ids lstInt_TblType READONLY
)
AS
BEGIN

    SET NOCOUNT ON;

        select *
    from dbo.dat_MetaData
    where MetaDataTypeID in (select n from @ids)
END
GO

最佳答案 找到了另一种方法去做.这种方式使用System.Data.SqlClient库创建与数据库的连接,指定存储过程名称,然后将参数作为DataTable传递,作为SQL Server用户定义的表类型.

using (SqlConnection conn = new SqlConnection(connStr)) {
    SqlCommand cmd = conn.CreateCommand();
    cmd.CommandType = System.Data.CommandType.StoredProcedure;
    cmd.CommandText = "dbo.usp_Test";
    cmd.Parameters.AddWithValue("@ids", dt);
    conn.Open();

    using (SqlDataReader sqlReader = cmd.ExecuteReader()) {
        DataTable retTbl = new DataTable();
        retTbl.Load(sqlReader);
    }
}
点赞