次のようなコードがある場合:
Something something = new Something();
BlahEntities b = new BlahEntities()
b.AddToSomethingSet(something);
b.SaveChanges();
トランザクション内でその追加をどのように実行しますか?
コードをTransactionスコープ内に配置できます
using(TransactionScope scope = new TransactionScope())
{
// Your code
scope.Complete(); // To commit.
}
TransactionScopeは、同じ名前のアセンブリにあるSystem.Transactions名前空間にあります(プロジェクトに手動で追加する必要がある場合があります)。
ObjectContextには、トランザクションの管理に使用できる接続プロパティがあります。
using (var context = new BlahEntities())
using (var tx = context.BeginTransaction())
{
// do db stuff here...
tx.Commit();
}
例外が発生した場合、トランザクションはロールバックされます。 BeginTransaction()の呼び出しには接続が必要であり、接続を開くため、BeginTransactionの呼び出しを拡張メソッドでラップすることは理にかなっています。
public static DbTransaction BeginTransaction(this ObjectContext context)
{
if (context.Connection.State != ConnectionState.Open)
{
context.Connection.Open();
}
return context.Connection.BeginTransaction();
}
このアプローチがTransactionScopeよりも有用であると私が考える1つのシナリオは、2つのデータソースにアクセスする必要があり、接続の1つでトランザクション制御のみが必要な場合です。その場合、TransactionScopeは、要求されない可能性のある分散トランザクションに昇格すると思います。
LINQ to SQLでは、既存のアンビエントトランザクションがない場合(TransactionScopeは「アンビエント」トランザクション)、データコンテキストがSubmitChanges()のトランザクションを作成することを知っています。 LINQ to Entitiesでこれが文書化されているのを見たことはありませんが、Entity Frameworkにも当てはまることを示唆する動作を見てきました。
したがって、関連するすべての変更に1つのSubmitChanges()(L2SQL)またはSaveChanges()(Linq to Entities)を使用している限り、TransactionScopeを使用しなくても問題ありません。 TransactionScopeが必要な場合
ネストされたTransactionScopesで問題が発生しました。それらは機能するはずであり、簡単なテストケースは機能しますが、実稼働コードに入ると、「内部」トランザクションは外部トランザクションと同じオブジェクトのようです。症状には、「トランザクションがコミットされました。このトランザクションを使用できなくなりました」または「このトランザクションオブジェクトはすでに破棄されています」などのエラーが含まれます。エラーは、内部トランザクションが処理を行った後に、外部トランザクションで発生します。
using System.Transactions;
using (TransactionScope scope = new TransactionScope())
{
try
{
using(DataContext contextObject = new DataContext(ConnectionString))
{
contextObject.Connection.Open();
// First SaveChange method.
contextObject.SaveChanges();
// Second SaveChange method.
contextObject.SaveChanges();
//--continue to nth save changes
// If all execution successful
scope.Complete();
}
}
catch(Exception ex)
{
// If any exception is caught, roll back the entire transaction and end the scope.
scope.Dispose();
}
finally
{
// Close the opened connection
if (contextObject.Connection.State == ConnectionState.Open)
{
contextObject.Connection.Close();
}
}
}
詳細な説明については、以下のリンクを参照してください https://msdn.Microsoft.com/en-us/data/dn456843.aspx
Entity Frameworkのすべてのバージョンで、SaveChanges()を実行してデータベースで挿入、更新、または削除を行うと、フレームワークはその操作をトランザクションでラップします。このトランザクションは、操作を実行するのに十分なだけ長く続き、その後完了します。そのような別の操作を実行すると、新しいトランザクションが開始されます。 Entity Frameworkの最新バージョン:6.0以降
詳細はこちら: EntityFramework and Transaction