【问题标题】:C# Scope_Identity IssueC# Scope_Identity 问题
【发布时间】:2013-01-17 16:49:09
【问题描述】:

浏览了一些答案,但似乎对我不起作用。

我需要返回一个表的 ID 字段,以便我可以在程序的不同部分使用它,我尝试过使用

    Convert.ToInt32(sqlComm.ExecuteScalar());

但运气不好,

    Convert.ToInt32(sqlComm.Parameters["ID"].Value);

即使记录确实插入到表中,两者都返回 0。

我将下面的代码转储,谁能看到我做错了什么?

    using (SqlConnection sqlConnect = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
        {
            using (SqlCommand sqlComm = new SqlCommand("up_Insert_Address", sqlConnect))
            {
                sqlComm.CommandType = CommandType.StoredProcedure;
                sqlComm.Parameters.Add("@AddressID", SqlDbType.BigInt).Direction = ParameterDirection.Output;
                sqlComm.Parameters.Add("@AddressLineOne", SqlDbType.NVarChar, 40).Value = address.AddressLineOne;   

                try
                {
                    sqlComm.Connection.Open();
                    return Convert.ToInt32(sqlComm.ExecuteScalar());
                }

                catch (SqlException)
                {
                }

                finally
                {
                    sqlComm.Connection.Close();
                }
            }
        }

和存储过程:

    @AddressID   Bigint OUTPUT,
    @AddressLineOne  NVarChar(40)
    AS
     BEGIN
      BEGIN TRY
      INSERT INTO Address
      (
         AddressLineOne
      )
      VALUES 
      (
         @AddressLineOne
      )

      SET @AddressID = SCOPE_IDENTITY();
    END TRY
    BEGIN CATCH
       DECLARE @Err nvarchar(500)
       SET @Err = ERROR_MESSAGE()
       RAISERROR(@Err, 16, 1)
    END CATCH
   END

【问题讨论】:

    标签: c# sql scope-identity executescalar


    【解决方案1】:

    你应该使用

    Convert.ToInt64(sqlComm.Parameters["@AddressID"].Value);
    

    使用ExceuteNonQuery 执行命令后。为了将来参考,ExecuteScalar 返回查询返回的结果集中第一行的第一列。您没有返回任何内容,只是设置了 OUTPUT 参数的值。

    你也绝对不能吞下任何SqlException。由于您的命令和连接已经在 using 块中,您不需要添加另一个 try/catch/finally。将其更改为:

    //try
    //{
        sqlComm.Connection.Open();
        sqlComm.ExecuteNonQuery();
        return Convert.ToInt64(sqlComm.Parameters["@AddressID"].Value);
        // using Int64 since the SQL type is BigInt
    //}
    
    //catch (SqlException)
    //{
    //}
    
    //finally
    //{
    //    sqlComm.Connection.Close();
    //}
    

    【讨论】:

    • 不客气 - 请查看我关于删除 catch 块的更新。
    • 我建议在结果(OUTPUT 参数)上使用long.TryParse() 作为防止引发异常的附加措施。它永远不会发生,但也许如果以后有人更改架构,这样现有代码会更容错。
    • @SiLo - 我不同意。返回值应始终为BigInt,而不是需要解析的字符串。铸造应该没问题。如果在强制转换时出现错误,你想要那个异常。
    • @D Stanley - 您的意思是在第一个代码示例中输入:Convert.ToInt32(sqlComm.Parameters["@AddressID"].Value);,在第二个代码示例中输入Convert.ToInt64(sqlComm.Parameters["@AddressID"].Value);
    • 我看到参数是BigInt后更正了。更正了第一个例子。
    【解决方案2】:
    var connectionstring = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
    
    var addressId = 0L; // long value (64bit)
    
    using (var connection = new SqlConnection(connectionString))
    using (var command = new SqlCommand("up_Insert_Address", connection))
    {
      command.CommandType = CommandType.StoredProcedure;
    
      command.Parameters.AddWithValue("@AddressID", addressId);    
      command.Parameters.AddWithValue("@AddressLineOne", address.AddressLineOne); 
    
      command.Parameters["@AddressID"].Direction = ParameterDirection.Output;
    
      try
      {
        if(connection.State != ConnectionState.Open)
          connection.Open();
    
        var rowsAffected = command.ExecuteNonQuery();
        addressId = Convert.ToInt64(command.Parameters["@AddressID"].Value);
      }
      catch (SqlException)
      {
        // Handle SQL errors here.
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-14
      • 2020-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-03
      • 1970-01-01
      相关资源
      最近更新 更多