web-dev-qa-db-ja.com

ID値を返すときのExecuteScalarとExecuteNonQuery

新しく挿入された行のID列を返す場合は、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. 出力パラメーターを使用しているため、ID値の取得はどちらの方法でも同じになりますか?
  3. いずれかの方法に関連するパフォーマンスヒットはありますか?
  4. 一般的にこれを全体的に行うより良い方法はありますか?

Visual Studio 2010、.NET 4.0、およびSQL Server 2008r2を使用しているので、違いが生じる場合があります。

22
techturtle

アーロンが提案したように、ストアドプロシージャを使用すると、SQL ServerがSQLバッチをコンパイルする作業を節約できるため、高速になります。ただし、ExecuteScalarまたはExecuteNonQueryのいずれかのアプローチを使用できます。私見、それらの間のパフォーマンスの違いは非常に小さいため、どちらの方法も「適切」です。

そうは言っても、出力パラメーターからID値を取得する場合、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 [〜#〜]:オブジェクトからdecimalに、そしてintに2回キャストする必要があることに注意してください(techturtleに感謝します)これに注意してください)。

28
Diego