単一のトランザクションで複数のデータベースの更新を管理する既存のコード セットを使用しています。簡単な例を次に示します。
Database db = DatabaseFactory.CreateDatabase();
using (DbConnection dbConnection = db.CreateConnection())
{
dbConnection.Open();
DbTransaction dbTransaction = dbConnection.BeginTransaction();
try
{
//do work
dbTransaction.Commit();
}
catch (Exception ex)
{
dbTransaction.Rollback();
}
}
新しい開発のために、この同じプロジェクトでも EntityFramework を使用しています。以下は、私のリポジトリ クラスの使用法の簡単な例です。
List<ThingViewModel> things = new List<ThingViewModel>();
// populate list of things
IObjectRepository thingRepository = new ThingRepository();
thingRepository.AddThings(things);
thingRepository.Save();
「AddThings」で行われた作業を、コードの最初のブロックでトランザクションの一部として実行したいと考えています。
リポジトリ パターンをこの既存のコードに、またはその逆にブレンドするクリーンな方法はありますか? 私は、既存のコードを完全に EntityFramework 内に書き直すことができる段階にはまだ達していないので、暫定的なアプローチを探しています。
古いコードからリポジトリ、つまり EntityFramework にトランザクションを渡そうとしましたが、うまくいかないようです。また、トランザクションに登録するために、ObjectContext を古いコードに戻そうとしました。どちらのアプローチも機能しません。
既存のコードを EntityFramework に移行する際に、このハードルに遭遇したのは私が初めてだとは信じられません...何か考えていないことがあるに違いありません。
以下に試したことをリストします。
using (TransactionScope transactionScope = new TransactionScope())
{
Database db = DatabaseFactory.CreateDatabase();
using (DbConnection dbConnection = db.CreateConnection())
{
dbConnection.Open();
DbTransaction dbTransaction = dbConnection.BeginTransaction();
try
{
//do work
dbTransaction.Commit();
}
catch (Exception ex)
{
dbTransaction.Rollback();
}
}
Thing thing = new Thing(){
Prop1 = Val1,
Prop2 = Val2
};
ThingObjectContext context = new ThingObjectContext();
context.Things.AddObject(thing);
context.SaveChanges();
transactionScope.Complete();
}
この最後の例は「動作」しますが、トランザクションとして機能しません。EF 挿入が失敗した場合、EL コマンドは TransactionScope によってロールバックされません。.Commit() と .SaveChanges() を明示的に呼び出さなければ、何も起こりません。可能であれば、これが同じ接続を共有することを本当に望んでいます。私が現在遊んでいるこの他の 2 つのバリエーションは、EF と EL の両方で同じ接続を使用しようとしているだけでなく、一方または他方で EnlistTransaction を使用しようとしています。これがMSDTCにならないように確実にしようとしています-それに関連する余分なオーバーヘッドは望ましくありません。