4

私は、それぞれがデータベースに永続化されるさまざまな種類のオブジェクトを持つアプリケーションを持っています。これはこれまでトランザクションなしでうまく機能しており、それらを追加するために暴走するつもりはありません。ただし、オブジェクトのコレクション全体が更新を開始する前に、トランザクションを開始して、コレクション内のすべてのオブジェクトが成功した場合にのみデータベースが実際に更新されるようにする必要がある場合があります。

たとえば、リンゴのコレクションがあるとします。すべてのリンゴを更新するコマンドがコレクションに発行されます。[トランザクションの開始はここにあります] 各リンゴはコードを実行して自分自身を更新します。[トランザクションのコミット/ロールバックはここで発生する必要があります]。

私が抱えているヒッチは、現在、各更新がアトミックであることです(トランザクションに明示的にラップされていません)。各「リンゴ」に ID を渡して、ある種のキャッシュに格納されたトランザクションを識別することができますが、更新中にキャッシュが無効になり、不要な問題が発生するリスクがあります。

では、これに対する最善のアプローチは何ですか?

4

4 に答える 4

4

まず、ページ内のトランザクション ロジックを処理しません。これを行うために、ある種のビジネス クラス (サービス、データ ユーティリティ クラス、ASP.Net から抽象化できるもの) を作成します。

次に、SQL Server などの分散トランザクションをサブスクライブできるデータベースを使用している場合は、TransactionScopeクラス (System.Transactions 名前空間で、System.Transactions.dll を参照) の使用を検討してください。

using(TransactionScope scope = new TransactionScope())
{
  SaveObjectOne(); //these are just psuedo-code statements
  SaveObjectTwo(); //replace these with your code that saves various objs
  SaveObjectThree();
  scope.Complete(); //this commits the transaction, unless exception throws
}

TransactionScope は IDisposable を実装しているため、Dispose()の呼び出しを使用すると、 Complete()が呼び出されなかった場合、トランザクションはロールバックされます。分散トランザクション コーディネーターがTransactionScopeを使用できるようにする必要があります。

于 2008-11-24T02:12:43.530 に答える
1

ado.net 2.0 では、トランザクションは非常にシンプルです。transactionscope を使用して、フレームワークにトランザクションを管理させることをお勧めします。

MSDNでそれについてすべて読んでください:

トランザクション フロー管理

トランザクション スコープは、直接的および間接的にネストできます。直接スコープのネストは、例 5 に示すように、別のスコープ内にネストされた単純なスコープです。

例 5. 直接スコープのネスト

using(TransactionScope scope1 = new TransactionScope())
{
   using(TransactionScope scope2 = new TransactionScope())
   {
      scope2.Complete();
   }
   scope1.Complete();
}

例 6TransactionScopeの の場合のように、独自のスコープを使用するメソッド内で fromを使用するメソッドを呼び出すと、間接的なスコープの入れ子が発生し ます。RootMethod()

例 6. 間接スコープのネスト

void RootMethod()
{
   using(TransactionScope scope = new TransactionScope())
   {
      /* Perform transactional work here */
      SomeMethod();
      scope.Complete();
   }
}

void SomeMethod()
{
   using(TransactionScope scope = new TransactionScope())
   {
      /* Perform transactional work here */
      scope.Complete();
   }
}
于 2009-10-13T16:46:57.250 に答える
1

OPは、コレクションがトランザクション内の他のすべてのオブジェクトの保存を管理しているため、ここにトランザクションコードを配置することは明らかだと述べています。ADO.Net を使用している場合、接続を開いてコレクション内のトランザクションを開始し、これを他の各オブジェクトに渡すのが最も簡単なオプションのようです。ここにある各オブジェクトはレイヤー スーパータイプ クラスから継承され、SQL Server を使用していると仮定しています。

public void Save()
{
    using (SqlConnection connection = new SqlConnection("Connection String"))
    {
        using (SqlTransaction trans = connection.BeginTransaction())
        {
            foreach (BusinessObject obj in this) 
            { 
                obj.Save(connection); 
            } 
            trans.Commit();
        }            
    }
}
于 2008-11-24T10:19:52.720 に答える
0
  1. 手動の DB トランザクションを実行するよりも、宣言型のトランザクションを好みます。
  2. Mitch Wheat が既に述べたように、トランザクションにはコンテキストがあり、接続ベースであるため、ページ/メソッドで発生した変更が含まれ、問題がなければコミットし、例外があった場合はロールバックします。
  3. ここで間違っているかもしれませんが、「ページ トランザクション」は .NET 1.1 のエンタープライズ サービス モデルを使用しており、MSDTC (分散トランザクション コーディネーター、登録済みの COM+ サービス) を介して動作しているように感じます...
  4. .NET 2.0 での宣言型トランザクションには、System.Transactions と LTM (軽量トランザクション マネージャー) が望ましい
  5. 私は Spring.NET フレームワーク トランザクション (ADO.NET と NHibernate の両方のバージョンで利用可能) を好みます。なぜなら、それらは AOP ベース (アスペクト指向プログラミング) の関心の分離をより適切にサポートしていると信じているからです。コードをトランザクション コードと結合する必要はありません。そして主な理由は、彼らが何年にもわたって Java でトランザクションを行ってきたからです。
于 2008-11-24T01:26:26.027 に答える