我有一个存储过程,该存储过程接受用户定义的表类型作为参数。在C#中,我使用SqlDataRecord和SqlMetaData(和SqlParameter)用我的数据创建一个表参数,并将其发送到存储过程。
当列(SqlMetaData)的顺序与实际表类型sql-server中的列定义的顺序相同时,这可以很好地工作。如果它们的顺序不同,那么错误的列将被匹配。
那么SqlMetaData.Name属性的意义是什么?它似乎被忽略了(至少在此用例中如此),并且只考虑了列(和数据)的顺序。
示例...
我在SQL中有一个表类型:
CREATE TYPE [dbo].[TestingTableParamType] AS TABLE(
[FName] VARCHAR(50) NULL,
[Numb] INT NULL,
[LName] VARCHAR(50) NULL
);
我有存储过程:
CREATE PROCEDURE spTEST_TableParam
@input TestingTableParamType READONLY
AS
SELECT FName, Numb, LName FROM @input
我有我的测试数据生成器方法,该方法生成三行测试数据,并以适当的顺序(以与TestingTableParamType定义匹配)具有适当的列类型。 但是,请注意,我使用空白字符串作为名称!我尝试使用无意义的字符串,而且效果也很好(空值会导致异常):
private IEnumerable<SqlDataRecord> genTestSqlDataRecords()
{
SqlDataRecord record = new SqlDataRecord(
new SqlMetaData("", SqlDbType.VarChar, 50),
new SqlMetaData("", SqlDbType.Int),
new SqlMetaData("", SqlDbType.VarChar, 50));
record.SetValues("fn1", 101, "ln1");
yield return record;
record.SetValues("fn2", 102, "ln2");
yield return record;
record.SetValues("fn3", 103, "ln3");
yield return record;
}
可以尝试指定列名并重新排序SqlMetaData列,但它只会使用列顺序来链接到表类型而不是列名。
数据库本身会执行一些其他代码,这是相关的代码段:
...
SqlParameter param = new SqlParameter("@input", SqlDbType.Structured);
param.Direction = ParameterDirection.Input;
param.TypeName = "TestingTableParamType";
param.Value = genTestSqlDataRecords();
dbCommand.Parameters.Add(param);
conn.Open();
var dataReader = dbCommand.ExecuteReader();
...
因此,看来SqlMetaData(列)Name属性无关紧要,至少在这种情况下如此。这会产生误导性代码-看起来您可以重新排序列(和数据),并且应该按其名称将它们匹配,但这不会发生!
另外,我看到的所有使用SqlDataRecord和SqlMetaData的示例都可以传递表类型参数,并根据需要为其列提供名称。
所有这些我错过了什么? 谢谢。
答案 0 :(得分:0)
SqlMetaData.Name属性的意义是什么?
此处都没有。但是对于CLR存储过程通过SendResultsStart
和相关方法或>>> test_dict = {"value1": 111.2, "value2": "asd", "value3": 13.232}
>>> test_dict = {key: int(math.floor(value)) if isinstance(value, float) else value for key, value in test_dict.items()}
>>> test_dict
{'value1': 111, 'value2': 'asd', 'value3': 13}
流式传输结果集而言,至关重要的是,在调用这些方法之前,SQL Server不知道“形状” 1是什么是结果集,并且它使用此元数据来理解它(并能够将该元数据转发回客户端应用程序)。
1 在谈论结果集时,我经常使用形状。它是列数,它们的名称和它们的数据类型。