返回标识值时,ExecuteScalar vs ExecuteNonQuery

时间:2013-01-09 21:21:53

标签: c# sql-server executenonquery executescalar

如果我想返回新插入行的标识列,请尝试确定是否最好使用ExecuteScalarExecuteNonQuery。我已阅读this question并了解其中的差异,但在查看几周前我写的一些代码时(虽然大量借用此网站)我发现在我的插页中我使用的是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. 通常有更好的方法来做到这一点吗?
  5. 我正在使用Visual Studio 2010,.NET 4.0和SQL Server 2008r2,以防万一。

1 个答案:

答案 0 :(得分:27)

正如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();

        }
    }
}

快乐的节目!

编辑:请注意,我们需要投两次:从对象到decimal,再到int(感谢techturtle注意到这一点)。