Udt as SQL 服务器 SP 参数通过空

Udt as SQL Server SP parameter coming through empty

我遇到了一个我无法理解的问题。我将用户定义的 table 类型作为参数从 C# 传递到 SQL 服务器存储过程,一旦到达 SP,table 中总是以 0 行结束。 .NET 代码是 Framework 4.7,SQL 服务器托管在 Azure 中。

SP定义为

CREATE PROCEDURE [dbo].[sp_ImportData]
    @ImportData udt_ImportData READONLY
AS
    INSERT INTO dbo.DEBUG ([Key], [Value])
         SELECT 'IMPORTDATA',
                (SELECT COUNT(1)
                   FROM @ImportData);

    ...
RETURN 0

udt 定义为

CREATE TYPE [dbo].[udt_ImportData] AS TABLE
(
    RecordId INT,
    RecordName NVARCHAR(100)
);

我调用 SP 的代码是

var table = new DataTable();
table.Columns.Add("RecordId", typeof(int));
table.Columns.Add("RecordName", typeof(string));

foreach (DataRow row in data.Rows)
{
    table.Rows.Add(row["RecordId"], row["RecordName"]);
}

using (var connection = new SqlConnection(_connectionString))
{
    var command = new SqlCommand("sp_ImportData", connection);
    SqlParameter tvpParam = command.Parameters.AddWithValue("@ImportData", table);
    tvpParam.SqlDbType = SqlDbType.Structured;
    tvpParam.TypeName = "dbo.udt_ImportData";

    connection.Open();
    command.ExecuteNonQuery();
}

在调试时,我检查了 table 变量在作为参数值附加之前确实有数据行。我还在 SP 中插入了一些调试代码,以便在传入后注销 @ImportData table 中的行数。这始终为零。我试过在参数名称中使用和不使用 @ 符号,我试过重命名参数(以防它是我不知道的保留字)。我尝试在 C# 中添加和删除 udt 名称的 "dbo." 前缀,但其中 none 有效。

如果有人能提供帮助,我将不胜感激;这让我发疯!我确定这是我没有看到的非常小的东西!

正如我在评论中所写 - 您没有在 C# 代码中指定命令类型。 CommandType 属性 的默认值是 CommandType.Text - 适合内联 sql 但不适合存储过程,因此您需要指定 CommandType.StoredProcedure。当我们这样做时,您不必指定参数的类型名称,而且您确实 should avoid using AddWithValue.
还有一件事 - SqlCommand 还实现了 IDisposable 接口,因此它也应该在 using 语句中使用:

using (var connection = new SqlConnection(_connectionString))
{
    using(var command = new SqlCommand("sp_ImportData", connection))
    {
        command.CommandType = CommandType.StoredProcedure;
        command.Parameters.Add("@ImportData", SqlDbType.Structured).Value = table;
        connection.Open();
        command.ExecuteNonQuery();
    }
}