我需要将整数数组传递给 .NET 中的存储过程,因此我在 Google 上搜索了该主题并最终在 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) 的类型特定元数据的类型无效。
方式二——使用列表作为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