0

単一のトランザクションで複数のデータベースの更新を管理する既存のコード セットを使用しています。簡単な例を次に示します。

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にならないように確実にしようとしています-それに関連する余分なオーバーヘッドは望ましくありません。

4

2 に答える 2

2

明示的なトランザクション管理の代わりに TransactionScope を使用します。コード全体を簡素化し、すべての操作で同じトランザクションを自動的に検出して使用する必要があります。

于 2012-06-21T15:36:40.437 に答える
1

ELコードDatabase.GetOpenConnection()の代わりに呼び出して、ブロック内で作成したものを渡す方法はありますか?私はこれをテストしていませんが、それが私が最初に試みることです。CreateConnection()things.ConnectionTransactionScope

于 2012-06-21T00:00:07.390 に答える