2009-04-17 17 views
6

DALの3つのデータベースにリクエストを発行するWebアプリケーションがあります。私はいくつかの統合テストを書いて、全体的な機能の往復が実際に何をすると期待しているかを確認しています。これは単なる私の単体テストとは全く別のものです。MSDTCが無効な場合、TransactionScope内の複数のデータベース接続をどうやって回避しますか?

私はこれらのテストを書くために意図された方法は、この

[Test] 
public void WorkflowExampleTest() 
{ 
    (using var transaction = new TransactionScope()) 
    { 
     Presenter.ProcessWorkflow(); 
    } 
} 

の効果に何かだったこの場合、プレゼンターは、すでに設定されています。この問題はProcessWorkflowメソッド内で発生します。これは、さまざまなリポジトリを呼び出して別のデータベースにアクセスし、SQL ServerボックスにMSDTCが有効になっていないため、新しいSQL接続を作成するか、キャッシュされた接続のデータベースを変更して別のデータベースをターゲットにします。私はこの問題を解決するための数多くの事をしようとしました

public void ProcessWorkflow() 
{ 
    LogRepository.LogSomethingInLogDatabase(); 
    var l_results = ProcessRepository.DoSomeWorkOnProcessDatabase(); 
    ResultsRepository.IssueResultstoResultsDatabase(l_results); 
} 

簡潔にするためにプレゼンターのような何かに似ています。

  1. キャッシュつのアクティブ常時接続し、ターゲット・データベースを変更する
  2. キャッシュ各ターゲット・データベースごとに1つのアクティブな接続(プーリングが私のためにこれを行う必要があるので、これは一種の無用だったが、私はどうかを確認したかったI彼らはTransactionScopeOptionを使用して、独自のトランザクションを持っているように、「RequiresNewのは、」

各リポジトリ内の追加TransactionScopesを追加する異なる結果)
  • を得たリスト上の私の第三の試みは、次のようになります。

    public void LogSomethingInLogDatabase() 
    { 
        using (var transaction = 
         new TransactionScope(TransactionScopeOption.RequiresNew)) 
        { 
         //do some database work 
    
         transaction.Complete(); 
        } 
    } 
    

    実際に私が試した3番目のことは、実際にユニットテストが動作するようにしましたが、実際に完了したすべてのトランザクションは私のデータベースです!だからこそ、完全な失敗は私のデータベースに影響を与えないことです。

    私の質問は、私がレイアウトした制約を踏まえて、私がやろうとしていることを達成するために他にどのような選択肢がありますか?

    EDIT:

    これは、 "//一部のデータベース作業を行う"

    using (var l_context = new DataContext(TargetDatabaseEnum.SomeDatabase)) 
    { 
        //use a SqlCommand here 
        //use a SqlDataAdapter inside the SqlCommand 
        //etc. 
    } 
    

    とのDataContext自体がこの

    public class DataContext : IDisposable 
    { 
        static int References { get; set; } 
        static SqlConnection Connection { get; set; } 
    
        TargetDatabaseEnum OriginalDatabase { get; set; } 
    
        public DataContext(TargetDatabaseEnum database) 
        { 
         if (Connection == null) 
          Connection = new SqlConnection(); 
    
         if (Connection.Database != DatabaseInfo.GetDatabaseName(database)) 
         { 
          OriginalDatabase = 
           DatabaseInfo.GetDatabaseEnum(Connection.Database); 
    
          Connection.ChangeDatabase(
           DatabaseInfo.GetDatabaseName(database)); 
         }   
    
         if (Connection.State == ConnectionState.Closed) 
         { 
          Connection.Open() //<- ERROR HAPPENS HERE 
         }  
    
         ConnectionReferences++;     
        } 
    
        public void Dispose() 
        { 
         if (Connection.State == ConnectionState.Open) 
         { 
          Connection.ChangeDatabase(
           DatabaseInfo.GetDatabaseName(OriginalDatabase)); 
         } 
    
         if (Connection != null && --ConnectionReferences <= 0) 
         { 
          if (Connection.State == ConnectionState.Open) 
           Connection.Close(); 
          Connection.Dispose(); 
         } 
        } 
    } 
    
  • +0

    私にはわかりません。作業単位はどういう意味ですか? – Joseph

    +0

    申し訳ありませんがここでは複数のデータベースサーバーまたは単一のサーバーへの複数の接続について話していますか? – meandmycode

    +0

    同じサーバー上の複数のデータベースまたは異なるサーバー上の複数のデータベース?それらが同じサーバー上にある場合、MSDTC – SQLMenace

    答えて

    1

    私はこの問題を回避する方法を見つけました。私がこの方法でやっている唯一の理由は、この問題を解決するために他の方法が見つからないことと、統合テストに入っているので、これが生産コードに悪影響を及ぼすのを心配していないからです。

    DataContextが破棄されているときに接続オブジェクトを破棄するかどうかを追跡するフラグとして機能するために、DataContextにプロパティを追加する必要がありました。この方法では、接続はトランザクション全体の範囲全体で生き続け、したがって、もはやここに私の新しい処分のサンプルですDTC

    を気にされていない:これは私の統合テストは、の形を取ることができます

    internal static bool SupressConnectionDispose { get; set; } 
    
    public void Dispose() 
    { 
        if (Connection.State == ConnectionState.Open) 
        { 
         Connection.ChangeDatabase(
          DatabaseInfo.GetDatabaseName(OriginalDatabase)); 
        } 
    
        if (Connection != null 
         && --ConnectionReferences <= 0 
         && !SuppressConnectionDispose) 
        { 
         if (Connection.State == ConnectionState.Open) 
          Connection.Close(); 
         Connection.Dispose(); 
        } 
    } 
    

    は:

    [Test] 
    public void WorkflowExampleTest() 
    { 
        (using var transaction = new TransactionScope()) 
        { 
         DataContext.SuppressConnectionDispose = true; 
    
         Presenter.ProcessWorkflow(); 
        } 
    } 
    

    これを実動コードで使用することはお勧めできませんが、統合テストでは適切だと思います。また、これはサーバーが常に同じで、ユーザーと同じ接続の場合にのみ機能します。

    これは私が持っていたのと同じ問題にぶつかる他の誰にも役立つことを願っています。

    0

    のようになりますどのようになるかであるあなたの場合MSDTCを使用したくない場合は、SQLトランザクションを直接使用することができます。

    SqlConnection.BeginTransaction()を参照してください。

    +0

    これは統合テストのコンテキストでどのように機能しますか?リポジトリレベルでBeginTransactionとCommitまたはRollbackを使用すると、トランザクションスコープの周りに全体をラップするとどうなりますか? – Joseph

    関連する問題