【问题标题】:Stored procedure called from code behaves different than in SQL Management Studio with NULL values从代码调用的存储过程的行为不同于在 SQL Management Studio 中使用 NULL 值
【发布时间】:2017-10-02 08:23:41
【问题描述】:

这是存储过程

CREATE PROCEDURE [Proc_DeleteSpecificRow]     
 @p_Id int
,@p_subId   int
,@p_col1 varchar(50) = NULL
,@p_col2 varchar(50) = NULL
,@p_col3 varchar(50) = NULL
AS        
BEGIN   
if(@p_col2 is not null AND @p_col3 is not null)
  Delete from TestTable where Id= @p_Id AND SubId= @p_subId
  AND col2= @p_col2 AND col3= @p_col3

当我在 SQL Server 管理工作室中使用以下值运行此存储过程时,它运行良好:

  • ID=1
  • SubId = 4
  • col1 = empty/null(我认为这可以解决问题!下面会详细介绍)
  • col2 = A
  • col3 = X

具有上述值的行被删除。如果我将 col2 和 col3 留空,并且只为 col1 提供一个值,也会发生同样的情况。它按预期工作。

现在,如果我使用 c# 代码中的等效数据/值调用此存储过程,它就不起作用。没有例外,它只是什么都不做。 我的猜测是,它与 NULL 值有关。这就是我将参数传递给 IDbCommand 的方式:

  • ID 为 DbType.Int16
  • SubID 为 DbType.Int16
  • col1 作为 DbType.String
  • col2 作为 DbType.String
  • col3 作为 DbType.String

重要提示:它与调用本身的内容无关,其他过程可以正常工作。

编辑(代码):

    [DataAccessorMethod(SupportedInterfacesFlags = AccessorInterfaces.IDataModifier)]
    public void DeleteSpecificRow(int id, int subId, string col1, string col2, string col3, string connectionString)
    {
      try
      {
        using (var scope = new TransactionScope(TransactionScopeOption.Required, Constants.TxOptions))
        {
          using (IDbConnection conn = new SqlConnection(connectionString))
          {
            IDbCommand cmd = MyHelper.GetCommand(conn, Constants.PROC_DELETESPECIFICROW, CommandType.StoredProcedure);
            MySqlHelper.AddParameter(cmd, "p_Id", DbType.Int16, id);
            MySqlHelper.AddParameter(cmd, "p_SubId" ,DbType.Int16, subId);
            MySqlHelper.AddParameter(cmd, "p_col1", DbType.String, col1);
            MySqlHelper.AddParameter(cmd, "p_col2", DbType.String, col2);
            MySqlHelper.AddParameter(cmd, "p_col3", DbType.String, col3);
            conn.Open();
            cmd.ExecuteNonQuery();
            scope.Complete();
          }
        }
      }
      catch (SqlException sqlex)
      {
      ...}
    }

【问题讨论】:

  • 我认为你也应该添加 C# 代码。
  • 好吧,我做了,但问题在文中描述。
  • 我看到你的参数 @p_Id 在 SP 中是 uniqueidentifier ,但在 C# 代码中是 int
  • 这只是我第一个版本的错字,我会编辑它

标签: c# sql-server


【解决方案1】:

当你从 c sharp 调用存储过程时,你可以从 SQL Server Profiler 中看到,语句是真还是假。

【讨论】:

    【解决方案2】:

    如果参数为 null,则 null 值的问题可能是 where 子句中的检查,因为例如col2 = null 不起作用。 相反,您可以对所有列尝试类似 AND (@p_col2 IS NULL OR @p_col = col2) 的操作。另一种方法是像ISNULL(@p_col, 999) = ISNULL(col2, 999)这样的肮脏黑客攻击

    【讨论】:

    • 如您所见,之前有一个 null 检查,因此您的情况永远不会发生:if(@p_col2 is not null AND @p_col3 is not null)。同样,它确实可以在 SQL Management Studio 中工作。
    【解决方案3】:

    我认为问题在于您没有将空值参数发送到存储过程。 您可以使用DBNull.Value 像这样传递空值

     MySqlHelper.AddParameter(cmd, "p_col1", DbType.String, 
                               string.IsNullOrEmpty(col1)? DBNull.Value : col1);
     MySqlHelper.AddParameter(cmd, "p_col2", DbType.String, 
                               string.IsNullOrEmpty(col2) ? DBNull.Value : col2);
     MySqlHelper.AddParameter(cmd, "p_col3", DbType.String, 
                               string.IsNullOrEmpty(col3) ? DBNull.Value : col3);
    

    另一种解决方案是将存储过程更改为

    if(isnull(@p_col2,'') != '' AND isnull(@p_col3,'') != '')
    begin
         -- do stuff
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-24
      • 2015-08-07
      • 2018-06-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多