2013-01-09 7 views
20

新しく挿入された行のID列を返す場合は、ExecuteScalarまたはExecuteNonQueryを使用するのが最善かどうかを確認しようとしています。私はthis questionを読んでいると私はそこの違いを理解しますが、(重く、このサイトからの借入ながら)私は数週間前に書いたいくつかのコードを見ているとき、私は私の挿入で、私はExecuteScalarを使用していたことがわかったので、のような:ID値を返すときにExecuteScalarとExecuteNonQueryを比較する

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; 
     } 
    } 
} 

これは私が必要なもののために正常に動作しますので、それは挿入を行うための「より適切」であるので、私は、私はここにExecuteNonQueryを使用するかどうか

  1. を思ったんだけど?
  2. 私は出力パラメータを使用しているので、アイデンティティ値の取得はどちらの方法でも同じですか?
  3. 一方的に関連するパフォーマンスヒットはありますか?
  4. これを全体的に行うより良い方法がありますか?

Visual Studio 2010、.NET 4.0、およびSQL Server 2008r2を使用しています。

+4

(1) 'ExecuteNonQuery'はなぜより適切なのですか? (2)ストアドプロシージャの使用を検討しましたか?そうでない場合は、どうしてですか?それは間違いなく、あなたがあなたのアプリに入れているアドホックなSQLのすべてをきれいにするのに役立ちます。あなたがそれを変更しなければならない場合は、アプリケーションを再コンパイルして再デプロイする必要があります。 –

+2

Hmmm ... ExecuteNonQueryは通常、結果を返すことを期待しないSQLを実行するためのものです。 ExecuteScalarはパラメータを渡す必要がないように値を返します。 – Sam

+2

私は出力パラメータなしで 'SELECT SCOPE_IDENTITY'を使うので' ExecuteScalar'を使います。したがって、あなたはSQLの最後の部分を 'SELECT SCOPE_IDENTITY();'に変更して 'return(int)cmd.ExecuteScalar();' 'ExecuteScalar'の目的である単一の値を取得します。 http://stackoverflow.com/a/9319609/284240 –

答えて

25

Aaronが提案したように、ストアドプロシージャは、SQLバッチのコンパイル作業をSql Serverに保存するため、処理速度が向上します。しかし、あなたはまだどちらかの方法で行くことができる:ExecuteScalarまたはExecuteNonQuery。 IMHO、それらのパフォーマンスの違いは非常に小さく、どちらの方法もまさに「正しい」ものです。

出力パラメータから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に(おかげでこれを注意するためにtechturtleします)。

+0

キャストの問題も発生しました。しかし、時にはそれが必要ではない、なぜだろうか? – SamChen

関連する問題