17

この問題は、ここの簡単な例では簡単に再現できませんが、誰かが経験やヒントを持っているかどうか疑問に思っていました.ここに問題があります:

  • エンティティ フレームワークの使用
  • アプリケーションには、(1) データが顧客などのエンティティテーブルに書き込まれる、(2) データが履歴テーブルに書き込まれる、多くのポイントがあります。
  • これらのアクションはどちらもEntity Framework を使用しますが、異なるコンテキストを使用します
  • これらのアクションは両方とも1 つのトランザクションで行う必要があります。つまり、一方が書き込みに失敗した場合、もう一方は書き込みを行うべきではありません。
  • それらをTransactionScopeでラップできます。

このような:

using (TransactionScope txScope = new TransactionScope()) {
    ...
}

しかし、これは私に与えます:

Microsoft 分散トランザクション コーディネーター (MSDTC) は、ネットワーク トランザクションに対して無効になっています。

データベース管理者から、MSDTCは選択により無効化されており、インストールできないとのことでした。

したがって、各コンテキストが同じ EntityConnection を使用するという考えで、 MetadataWorkspace を使用して独自の EntityConnection を作成しようとして変更を加えています。ただし、これを機能させることはほぼ不可能であることが証明されています。たとえば、理論的には両方のコンテキストが EntityConnection を使用しているにもかかわらず、現在、上記のエラーが発生し続けています。たとえば、Entity Framework が MSDTC を必要とする場所/理由を理解するのは困難です。

共有する経験やコード例を持っている人はいますか?

4

3 に答える 3

13

さて、問題はとても簡単です。

SQL Server 2008 を使用している場合、昇格可能なトランザクションがあるため、その問題は発生しません。.NET は、同じ永続ストア (データベース) を使用していることを認識しているため、DTC に昇格してローカルとしてコミットしません。SQL Server 2008 とのプロモーション可能なトランザクションを調べます。

私が知る限り、オラクルはプロモーション可能なトランザクションをサポートするためにドライバーで動作していますが、状態はわかりません。MS オラクル ドライバーはそれをサポートしていません。 http://www.oracle.com/technology/tech/windows/odpnet/col/odp.net_11.1.0.7.20_twp.pdf

昇格可能なトランザクションをサポートしないドライバーを使用している場合、.NET が 2 つの接続を行うローカル トランザクションを使用することはできません。アーキテクチャを変更するか、データベース管理者に MSDTC をインストールするよう説得する必要があります。

于 2010-03-03T11:07:40.137 に答える
1

あなたがする必要があるのは、コンテキストが単一のデータベース接続を共有するように強制することだと思います。その後、単一のトランザクションで 2 つの異なるコンテキストに対してこれら 2 つの操作を実行できます。これを実現するには、1 つの EntityConnection オブジェクトをコンテキストの両方のコンストラクターに渡します。もちろん、このアプローチでは、このオブジェクトを DB を更新するメソッドに渡す必要があります。

私は最近、複数の EF コンテキストとトランザクションの使用を容易にするデータベース コンテキスト スコープの作成についてブログを書きました。

于 2013-01-05T19:12:48.310 に答える
1

SQL 2008、Entity Framework でも同様の問題がありました。

2 つのフレームワーク (EF1 と EF2) を定義しましたが、SQL 2008 データベースと同じ接続文字列を使用しました。

ネストされた「usings」を両方で使用すると、上記の MSDTC エラーが発生しました。たとえば、コードは次のようになりました。

using (TransactionScope dbContext = new TransactionScope())
{
     using (EF1 context = new EF1())
     {
         // do some EF1 db call
         using (EF2 context2 = new EF2())
         {
              // do some EF2 db call
          }
      }
      dbContext.Complete();
}

いくつかのメソッドに分割されているため、これほど単純ではありませんでしたが、これが「usings」の基本構造でした。

修正は、一度に 1 つだけを使用して開くことでした。MTDSC エラーはありません。データベースで分散トランザクションを開く必要はありません。

using (TransactionScope dbContext = new TransactionScope())
{
     using (EF1 context = new EF1())
     {
         // do some EF1 db call

      }
     using (EF2 context2 = new EF2())
     {
              // do some EF2 db call
     }
     dbContext.Complete();
}
于 2012-02-16T23:07:46.930 に答える