2011-03-07 14 views
3

私はEntity Framework 4を使用して非常に単純なデータベースを作成しました。エンティティでトランザクションを使用できるようにしたいのですが、変更をロールバックしないように見えません。エンティティがデータベースに保存される前に一時的な変更を放棄する方法が必要です。Entity Frameworkオブジェクトコンテキストでトランザクションを実行する方法は?

たとえば、次のコードでは、エンティティフレームワークオブジェクトコンテキスト "MusicContainer"を使用しています。 TransactionScope内で、アーティストエンティティが作成されます。トランザクションは完了せずに終了します。私はトランザクションがロールバックされることを期待しています。しかし、プログラムは、あたかも最初にTransactionScopeを作成したことがないかのように動作します。 TransactionScopeの終了後、music.SaveChanges()行はオブジェクトをデータベースに保存します。エンティティフレームワークは、TransactionScopeの私はここにそれを期待してい方法を使用していない場合は

class Program 
{ 
    static void Main(string[] args) 
    { 
     using (MusicContainer music = new MusicContainer()) 
     { 
      using (TransactionScope transaction = new TransactionScope()) 
      { 
       Artist artist = new Artist { Name = "Test" }; 
       music.Artists.AddObject(artist); 
      } 
      // The transaction ended without Complete(); shouldn't the changes be abandoned? 
      music.SaveChanges(); 
     } 
    } 
} 

、どのように私は私が探している機能を得ることができますか?関数の呼び出し元がMusicContainerを渡すいくつかの状況があります。関数から戻る前にMusicContainerをクリーンな状態にしておく必要があります(つまり、別のSaveChangesで誤って保存されないように変更をロールバックします同じMusicContainerオブジェクトにある)。

答えて

7

あなたはSaveChanges()は、すべてのことが必要なのである、このシナリオでは全くTransactionScopeを必要としない - あなたはMusicContainerで別のusingのブロックを持っている場合、これは別のトランザクションになり、内のすべての変更を保存しませんあなたの現在のusingブロックTransactionScopeは、複数のDBコンテキストにまたがるトランザクションにのみ必要です。

一般に、コンテキストは、完了した後に関連する操作で構成される作業単位としてのみ使用してください。SaveChanges()。関連のない独立した作業単位ごとに新しいコンテキストを開きます。あなたのシナリオではこれを使用してください:

​​
+0

私は、各取引で別々の "using(MusicContainer music = new MusicContainer())"を使用することをお勧めしますか?私が最初に疑ったのは、このようなことが並行して数十件あると、これがボトルネックになるということでした。私はそれを考えるのが間違っていますか? –

+2

@notfed DB接続は、必要に応じて、つまり 'SaveChanges()'を呼び出すときやクエリを実行するときにだけ使用されます。このMSDNの記事もチェックしてください:http://msdn.microsoft.com/ ja-us/library/cc853327.aspx – BrokenGlass

+2

@notfed:トランザクションごとに新しいコンテナを使用する必要があります。ここをクリックしてください:http://stackoverflow.com/questions/3653009/entity-framework-and-connection-pooling/3653392#3653392 –

2

あなたは間違った場所にSaveChangesを持っています。

class Program 
{ 
    static void Main(string[] args) 
    { 
     using (MusicContainer music = new MusicContainer()) 
     { 
      using (TransactionScope transaction = new TransactionScope()) 
      { 
       Artist artist = new Artist { Name = "Test" }; 
       music.Artists.AddObject(artist); 
       music.SaveChanges(); 
      } 
      // The transaction ended without Complete(); the changes are abandoned? 
     } 
    } 
} 

トランザクションが失敗した場合は、MusicContainerを再利用しないでください。各Unit of Work

+0

私は意図的に間違った場所にSaveChangesを持っています。私の主張は、私が与えたコードでは、なぜSaveChangesはそれらの変更を保存しているのですか? –

+1

MusicContainerの前にTransactionScopeを宣言する必要があります。 – edze

0

エンティティフレームワークのための新しいものを作成しのTransactionScopeを使用することができるはずです。このメソッドによってのみ指定された変更をロールバックする必要がある場合は、新しいTransactionScopeを開始する必要があります。

using (MusicContainer music = new MusicContainer()) 
    { 
    using (TransactionScope transaction = new TransactionScope(TransactionScopeOptions.RequiresNew)) 
      { 
       Artist artist = new Artist { Name = "Test" }; 
       music.Artists.AddObject(artist); 
       music.SaveChanges(); 
       scope.Complete(); 
      } 
    } 
+0

さて、私が呼び出し元関数からMusicContainerを渡している場合、私は、TransactionScope内にMusicContainerを作成するオプションはありません。 –

+0

その後、メソッドでSaveChangesを呼び出す必要はありません。トップレベルの関数がSaveChangesを呼び出すようにしてください。 – Amitabh

+0

しかし、オブジェクトコンテキストに加えられた変更を_abandon_する必要があり、呼び出し側に変更を保存させたくありません。 –

関連する問題