2010-11-26 13 views
2

私はこの質問が前に尋ねられていることを認識していますが、実際にはまだ答えが見つかっていません。TransactionScopeとDataContext

私の問題は、私のユニットテストがLinqを使ってデータベースに問い合わせるWebサービスを呼び出そうとしているときに発生します。

ユニットテストがそのようにように設定されています

[TestInitialize] 
public void SetUp() 
{ 
    var scope = new TransactionScope(TransactionScopeOption.Required,TimeSpan.MaxValue); 
    var database = new DatabaseDataContext(); 
} 

[TestCleanup] 
public void TearDown() 
{ 
    scope.Dispose(); 
    database.Dispose(); 
} 

[TestMethod] 
public void GetCategoryList_Success() 
{ 
    // create test data 
    var result = service.GetItems(); 
} 

はservice.GetItems方法はとてもようになります:LINQクエリを実行しようとすると

try 
{ 
    using (DatabaseDataContext database = new DatabaseDataContext()) 
    { 
     var items = (from i in database.Items 
        select i).ToList<Items>(); 
     return items; 
    } 
} 
catch (Exception ex) 
{ 
    // log error 
    return null; 
} 

、次の例外がスローされます。

操作はトランザクションの状態に対して有効ではありません。

これはネストされたトランザクションと関係していると思いますが、テストデータが実際にデータベースに保存されないように、トランザクションをテストクラスに保存しておく必要があります。走る

また、私のホストは共有インスタンス上にあるため、サーバーを直接変更することはできません。

これをそのまま動作させる方法はありますか?あるいは、このコンテキストでTransactionScopeを使用する方法がありますか?

答えて

0

単一のTransactionScope内で同じデータベースに2つの接続を作成しようとしています.1つはテストプロセス用、もう1つはWebサービスプロセス用です。これは、異なるプロセスからのデータベースのトランザクションが明らかにネストできないために機能しません。

ここでのテスト方法を変更する必要があります。 Janの答えをお読みください。

回避策として、Webサービスでトランザクションを管理できるようにすることができます。メソッドBeginGlobalTranは、(サービスに格納されている)Webサービス用のグローバルTransaction(またはTransactionScope)オブジェクトを作成し、他のすべてのメソッドはこのオブジェクトを使用する必要があります(したがって、他のすべてのトランザクションは 'global'トランザクション内にネストされます)。もう1つの方法はRollbackGlobalTranで、この 'グローバル'トランザクションをロールバックする必要があります。
これは回避策であり、いくつかの予期しない副作用を引き起こす可能性があります(たとえば、メソッドのエラーにより 'グローバル'トランザクションがコミットできなくなるため、エラーを避けるために再起動する必要があります)。