通过SqlDataRecord传递到用户定义的表类型时,SqlMetaData.Name似乎无关紧要

时间:2019-03-27 04:02:28

标签: c# sql-server tsql

我有一个存储过程,该存储过程接受用户定义的表类型作为参数。在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的示例都可以传递表类型参数,并根据需要为其列提供名称。

所有这些我错过了什么? 谢谢。

1 个答案:

答案 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 在谈论结果集时,我经常使用形状。它是列数,它们的名称和它们的数据类型。