【问题标题】:Udt as SQL Server SP parameter coming through empty作为 SQL Server SP 参数的 Udt 来自空
【发布时间】:2018-02-23 00:22:50
【问题描述】:

我遇到了一个我无法理解的问题。我将用户定义的表类型作为参数从 C# 传递到 SQL Server 存储过程,并且一旦到达 SP,表中的行总是以 0 行结束。 .NET 代码是 Framework 4.7,SQL Server 托管在 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();
}

在调试时,我检查了表变量中实际上存在数据行,然后才将其作为参数值附加。我还在 SP 中插入了一些调试代码,以便在传入后注销 @ImportData 表中的行数。这总是为零。我尝试在参数名称中使用和不使用 @ 符号,我尝试重命名参数(以防它是我不知道的保留字)。我试过添加和删除“dbo”。 C# 中 udt 名称的前缀,但这些都不起作用。

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

【问题讨论】:

  • 这取决于我正在运行的场景,但一般在 40,000 左右。有限制吗?
  • 我认为存储过程的内容与问题无关;我已经用我正在使用的调试行更新了它。我可以毫无问题地从 SSMS 调用它;一切正常。我几乎可以肯定问题出在我从 C# 调用 SP 的方式上。
  • 您调试了代码并明确检查了command.ExecuteNonQuery 上的table.Rows.Count 的值?
  • 我看到您的 c# 代码中缺少的一件事是 command.CommandType = CommandType.StoredProcedure,但我不确定这是否是问题所在。另外,您可以使用Add("@ImportData", SqlDbType.Structured).Value = table; 而不是AddWithValue - 但我很确定这不是问题。
  • 你,先生 (@ZoharPeled) 是个天才!我错过了CommandType。我已经把它放进去,一切正常。非常感谢!

标签: c# sql-server stored-procedures user-defined-types


【解决方案1】:

正如我在评论中所写 - 您没有在 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();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-30
    • 1970-01-01
    • 1970-01-01
    • 2016-05-23
    相关资源
    最近更新 更多