26

试图弄清楚它是否最好使用ExecuteScalar,或者ExecuteNonQuery我是否想返回新插入行的标识列。我已经阅读了这个问题并且我理解那里的差异,但是当查看我几周前编写的一些代码时(同时从这个网站大量借用)我发现在我的插入中我使用的是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,以防万一。

4

1 回答 1

32

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

        }
    }
}

快乐编程!

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

于 2013-01-11T22:51:42.013 回答