web-dev-qa-db-ja.com

ADO.NETのリファクタリング-SqlTransactionとTransactionScope

ADO.NET SqlCommandオブジェクトを作成し、データベース(SQL Server 2005)に保存するアイテムのリストをループする小さなC#メソッドを「継承」しました。

現在、従来のSqlConnection/SqlCommandアプローチが使用されており、すべてが機能することを確認するために、2つの手順(古いエントリを削除してから新しいエントリを挿入する)がADO.NETSqlTransactionにラップされています。

using (SqlConnection _con = new SqlConnection(_connectionString))
{
   using (SqlTransaction _tran = _con.BeginTransaction())
   {
      try
      {
         SqlCommand _deleteOld = new SqlCommand(......., _con);
         _deleteOld.Transaction = _tran;
         _deleteOld.Parameters.AddWithValue("@ID", 5);

         _con.Open();

         _deleteOld.ExecuteNonQuery();

         SqlCommand _insertCmd = new SqlCommand(......, _con);
         _insertCmd.Transaction = _tran;

         // add parameters to _insertCmd

         foreach (Item item in listOfItem)
         {
            _insertCmd.ExecuteNonQuery();
         }

         _tran.Commit();
         _con.Close();
       }
       catch (Exception ex)
       {
          // log exception
          _tran.Rollback();
          throw;
       }
    }
}

さて、私は最近.NET TransactionScopeクラスについてたくさん読んでいます、そして私はここで好ましいアプローチは何であるか疑問に思いましたか?使用に切り替えることで何か(読みやすさ、速度、信頼性)を得ることができますか

using (TransactionScope _scope = new TransactionScope())
{
  using (SqlConnection _con = new SqlConnection(_connectionString))
  {
    ....
  }

  _scope.Complete();
}

何を好みますか、そしてその理由は何ですか?

マーク

27
marc_s

TransactionScopeを使用するように既存のコードを切り替えても、すぐには何も得られません。柔軟性があるため、将来の開発に使用する必要があります。将来的には、ADO.NET呼び出し以外のものをトランザクションに含めることが容易になります。

ところで、投稿された例では、SqlCommandインスタンスはusingブロックにある必要があります。

16
John Saunders

マイクロソフトでは、トランザクションスコープの使用を推奨しています。

http://msdn.Microsoft.com/en-us/library/system.transactions.transactionscope.aspx

基本的な考え方は、トランザクションスコープが「アンビエントトランザクションコンテキスト」を管理するということです。最初に1つのデータベースと通信し、SQLトランザクションがあり、次にデータベース番号2と通信すると、トランザクションは分散トランザクションに昇格されます。

トランザクションスコープは機能するので、配管ではなくシステムの機能に集中できます。

[〜#〜]編集[〜#〜]

トランザクションスコープを使用すると、そのスコープ内のすべてがトランザクションの対象になります。したがって、コマンドをトランザクションに接続するコード行を保存します。これはエラーの原因となる可能性があります。たとえば、この行が忘れられた可能性が1000回に1回あった場合、何回欠落しますか。

編集2

以下のTriynkoに関するコメントに同意します。ただし、Entity Frameworkを使用しているため、EFは接続を自動的に閉じて再度開き、トランザクションに参加させます。接続を物理的に閉じるのではなく、接続プールに解放して新しい接続を取得します。新しい接続は、同じものでも異なるものでもかまいません。

8
Shiraz Bhaiji

私はTransactionScopeを好みます。すべてのシナリオで完全に機能するわけではありませんが、説明するシナリオでは、より優れたソリューションです。

私の推論:

  1. トランザクションへの参加は自動的に行われます
  2. 例外が発生した場合のトランザクションのロールバックは自動的に行われます

システムが詳細の一部を処理しているため、コードが少し少なくなり、一般的に堅牢な設計になります。それは私がしなければならないことの1つ少ないことです。

さらに、透過的なトランザクション登録は、DALにネストされたメソッドが多数ある場合に特に役立ちます。ただし、トランザクションが誤ってDTCを必要とする分散メソッドに変換されないように注意する必要があります。同じDBを指している場合でも、複数のSqlConnectionsを使用します。

8
RickNZ

DTC、ファイアウォールなどの設定など、サーバーで実行する必要のある多くの設定のため、トランザクションスコープを使用すると、多くの問題が発生する場合があることに注意してください。したがって、実装でSqlTransactionを使用する方が節約できることをお勧めします。

6
Wawan

また遅い...データベースがネストされたトランザクションをサポートしていない場合でも、ビジネス層に「ネストされた」トランザクションを簡単に含めることができます。 .NETはネストを制御し、最終的に1つのデータベーストランザクションを使用します(少なくともSQL Server 2008以降の場合)。これにより、より大きなトランザクションの一部として、元の意図の外でデータアクセスコードを再利用することがはるかに簡単になります。

2

わかりました、多分これには遅すぎます...しかしとにかく、私は興味のある人のためにそれを書き留めます...

私は今より良い絵を持っているので、私の現在のSqlTransactionベースのアプローチで多くの困難を抱えた後、私が見るようにTransactionScopeを支持して変更するかもしれません...TransactionScopeの主な利点はそれは使用できますビジネスレイヤーで非常に簡単に

2
Learner