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

标签 asp.net sql-server-2008

我需要将整数数组从 .NET 传递到存储过程,因此我用 google 搜索了该主题,最终找到了 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 });

我得到的异常(exception)情况是: 传入的表格数据流 (TDS) 远程过程调用 (RPC) 协议(protocol)流不正确。参数 1(“@ids”):数据类型 0x62 (sql_variant) 对于特定于类型的元数据具有无效类型。

方式二-使用List作为Sql参数

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 });

我得到的这个异常(exception)是: 不存在从对象类型 System.Collections.Generic.List`1[[Microsoft.SqlServer.Server.SqlDataRecord, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] 到已知对象的映射托管提供商 native 类型。

其他信息 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 传入,该 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);
    }
}

关于asp.net - SQL Server 用户定义的表类型和 .NET,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10624394/

相关文章:

asp.net 成员(member)提供商 Guid userID

c# - 请求的操作超时已过期

sql - 检查 varbinary(max) 列是否为 null 真的很慢

sql-server-2008 - sql server每日平均

sql - 为什么 sql case 不适用于 int 列的 null 条件

sql-server - SQL Server 2008 r2 - T-SQL LIKE 或 PATINDEX 匹配 A-Z、0-9、连字符、句点、下划线和波形符以外的字符

sql-server - SQL Server VARBINARY INSERT 锁定表 30 分钟以上

c# - 检查查询字符串是否为 int 的最佳方法?

c# - 在 TableCell() 中的单元格之间添加空格

asp.net - 如何将文件从 ASP.NET 上传到另一个 Web 应用程序