当返回标识值时,ExecuteScalar vs ExecuteNonQuery

本文关键字:ExecuteScalar vs ExecuteNonQuery 返回 标识 | 更新日期: 2023-09-27 17:51:12

试图弄清楚如果我想返回新插入行的身份列,是否最好使用ExecuteScalarExecuteNonQuery。我已经阅读了这个问题,我理解那里的差异,但是当查看我几周前写的一些代码时(同时从这个网站大量借用),我发现在我的插入中我使用的是ExecuteScalar,像这样:

public static int SaveTest(Test newTest)
{
    var conn = DbConnect.Connection();
    const string sqlString = "INSERT INTO dbo.Tests ( Tester , Premise ) " +
                             "               VALUES ( @tester , @premise ) " +
                             "SET @newId = SCOPE_IDENTITY(); ";
    using (conn)
    {
        using (var cmd = new SqlCommand(sqlString, conn))
        {
            cmd.Parameters.AddWithValue("@tester", newTest.tester);
            cmd.Parameters.AddWithValue("@premise", newTest.premise);
            cmd.Parameters.Add("@newId", SqlDbType.Int).Direction = ParameterDirection.Output;
            cmd.CommandType = CommandType.Text;
            conn.Open();
            cmd.ExecuteScalar();
            return (int) cmd.Parameters["@newId"].Value;
        }
    }
}

这对我需要的东西很好,所以我想知道

  1. 我是否应该在这里使用ExecuteNonQuery,因为它是"更合适"做插入?
  2. 检索身份值是相同的方式,因为我使用输出参数?
  3. 是否存在与某种方式或其他方式相关的性能影响?
  4. 总的来说有没有更好的方法来做到这一点?

我使用的是Visual Studio 2010, . net 4.0和SQL Server 2008r2,以防有任何不同

当返回标识值时,ExecuteScalar vs ExecuteNonQuery

正如Aaron所建议的,存储过程将使它更快,因为它节省了Sql Server编译Sql批处理的工作。但是,您仍然可以使用任何一种方法:ExecuteScalarExecuteNonQuery。恕我直言,它们之间的性能差异如此之小,以至于任何一种方法都是"适当的"。

话虽如此,如果您从输出参数中获取身份值,我不认为使用ExecuteScalar有什么意义。在这种情况下,ExecuteScalar返回的值变得无用。

一种我喜欢的方法,因为它需要更少的代码,使用ExecuteScalar不带输出参数:

public static int SaveTest(Test newTest)
{
    var conn = DbConnect.Connection();
    const string sqlString = "INSERT INTO dbo.Tests ( Tester , Premise ) " +
                             "               VALUES ( @tester , @premise ) " +
                             "SELECT SCOPE_IDENTITY()";
    using (conn)
    {
        using (var cmd = new SqlCommand(sqlString, conn))
        {
            cmd.Parameters.AddWithValue("@tester", newTest.tester);
            cmd.Parameters.AddWithValue("@premise", newTest.premise);
            cmd.CommandType = CommandType.Text;
            conn.Open();
            return (int) (decimal) cmd.ExecuteScalar();
        }
    }
}

编程快乐!

EDIT:请注意,我们需要两次强制转换:从object到decimal,然后到int(感谢techturtle注意到这一点)。