【问题标题】:Why is my SQL CLR stored proc call claiming I am not providing a parameter I am?为什么我的 SQL CLR 存储过程调用声称我没有提供我的参数?
【发布时间】:2014-04-10 02:05:16
【问题描述】:

在 CLR 过程中,我有以下方法:

private static void EndOwnershipForTeam(long assetId, int teamId)
{
    const string storedProcedureName = @"up_RemoveAssetOwnershipFromTeam";

    using (var connection = new SqlConnection("context connection=true"))
    using (var command = new SqlCommand(storedProcedureName, connection))
    {
        command.Parameters.AddWithValue("assetId", assetId);
        command.Parameters.AddWithValue("teamId", teamId);

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

当我运行此方法时,我收到以下错误:

消息 6522,级别 16,状态 1,过程 cp_RemoveAsset,第 0 行

在执行用户定义的例程或聚合“cp_RemoveAsset”期间发生 .NET Framework 错误:

System.Data.SqlClient.SqlException:过程或函数“up_RemoveAssetOwnershipFromTeam”需要参数“@assetId”,但未提供。

System.Data.SqlClient.SqlException:

在 System.Data.SqlClient.SqlConnection.OnError(SqlException 异常, Boolean breakConnection)

在 System.Data.SqlClient.SqlCommand.RunExecuteNonQuerySmi(Boolean sendToPipe)

在 System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult 结果, String methodName, Boolean sendToPipe)

在 System.Data.SqlClient.SqlCommand.ExecuteNonQuery()

在 StoredProcedures.EndOwnershipForTeam(Int64 assetId, Int32 teamId)

在 StoredProcedures.cp_RemoveAsset(SqlInt32 userId, SqlString xaid)

既然我的代码提供了参数(通过SqlContext.Pipe.Send() 调用显示输出来验证),为什么它声称我没有提供我实际提供的参数?

【问题讨论】:

  • 您的 proc 是否调用任何其他程序?如果是这样,我会检查您是否正确地向那些提供参数。
  • 指定命令类型:command.CommandType = CommandType.StoredProcedure;

标签: c# sqlclr


【解决方案1】:

看起来像写的那样,您的代码正在指示 SQL Server 尝试执行此操作:

up_RemoveAssetOwnershipFromTeam

换句话说,只是没有提供参数的过程。

要连接参数,您需要指定 CommandType.StoredProcedure,或显式连接命令参数:

// option 1
private static void EndOwnershipForTeam(long assetId, int teamId)
{
    const string storedProcedureName = @"up_RemoveAssetOwnershipFromTeam";

    using (var connection = new SqlConnection("context connection=true"))
    using (var command = new SqlCommand(storedProcedureName, connection))
    {
        command.CommandType = CommandType.StoredProcedure;
        command.Parameters.AddWithValue("assetId", assetId);
        command.Parameters.AddWithValue("teamId", teamId);

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

// option 2
private static void EndOwnershipForTeam(long assetId, int teamId)
{
    const string sql = @"exec up_RemoveAssetOwnershipFromTeam @assetId, @teamId";

    using (var connection = new SqlConnection("context connection=true"))
    using (var command = new SqlCommand(sql, connection))
    {
        command.Parameters.AddWithValue("@assetId", assetId);
        command.Parameters.AddWithValue("@teamId", teamId);

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

【讨论】:

  • 是的,这就是问题所在。我忘记将命令类型设置为存储过程!
  • 好收获。尽管如果命令文本形成参数化查询并匹配查询参数,则将使用提供的参数。
【解决方案2】:

您在行中遗漏了@ 符号

command.Parameters.AddWithValue("assetId", assetId);
command.Parameters.AddWithValue("teamId", teamId);

他们应该是

command.Parameters.AddWithValue("@assetId", assetId);
command.Parameters.AddWithValue("@teamId", teamId);

【讨论】:

  • @不是必需的
  • @Siyual 在某些情况下它是必需的,尽管我不确定这是否是其中之一。
  • 某些方法可能是允许的,但 SqlParameter.ParameterName 的 MSDN 文档指出 @ 是必需的,因此最安全的选择是始终使用它。
  • 我认为在这种情况下它是必需的。是否assetId 是引用类型而不是long,如果它是null,可能会导致相同的错误,但这里不是这种情况。
  • 在存储过程调用中,@ 不是必需的。
【解决方案3】:
  1. 您省略了“@”前缀。
  2. 为您的 sql 服务器和/或数据库配置的默认排序规则是什么?如果区分大小写,则需要完全匹配大小写。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-29
    • 1970-01-01
    • 2022-12-17
    • 1970-01-01
    • 2019-03-22
    相关资源
    最近更新 更多