以下のコードを参照してください。複数のエンティティコンテキストを初期化すると、2番目のコードのみのセットで次の例外が発生します。 2番目のセットをコメントアウトすると機能します。
{「基になるプロバイダーはオープンで失敗しました。」}
内部:{「基になるトランザクションマネージャーとの通信に失敗しました。」}
内部:{「COMコンポーネントへの呼び出しからエラーHRESULT E_FAILが返されました。」}
これはサンプルアプリであり、2つのコンテキストを続けて作成しても意味がないことを知っています。ただし、製品コードには同じTransactionScope
に複数のコンテキストを作成する理由があり、これは変更できません。
編集
これは、MS-DTCをセットアップしようとしている私の前の質問です。サーバーとクライアントの両方で有効になっているようです。正しく設定されているかどうかはわかりません。また、これを実行しようとしている理由の1つは、TransactionScope
内の既存のコードがADO.NETとLinq 2 Sqlを使用していることです。これらにも同じトランザクションを使用してほしいと思います。 (それはおそらくクレイジーに聞こえますが、可能であればそれを機能させる必要があります)。
C#でTransactionScopeを使用するにはどうすればよいですか?
ソリューション
WindowsファイアウォールがMS-DTCへの接続をブロックしていました。
using(TransactionScope ts = new System.Transactions.TransactionScope())
{
using (DatabaseEntityModel o = new DatabaseEntityModel())
{
var v = (from s in o.Advertiser select s).First();
v.AcceptableLength = 1;
o.SaveChanges();
}
//-> By commenting out this section, it works
using (DatabaseEntityModel o = new DatabaseEntityModel())
{
//Exception on this next line
var v = (from s1 in o.Advertiser select s1).First(); v.AcceptableLength = 1;
o.SaveChanges();
}
//->
ts.Complete();
}
MS-DTC(分散トランザクションコーディネーター)が何らかの理由で正しく機能していません。 MS-DTCは、複数のSQL接続を含む複数の異種リソースにわたるトランザクションの結果を調整するために使用されます。
何が起こっているかについての詳細は このリンク を見てください。
基本的に、MS-DTCが実行され、適切に機能していることを確認すれば、エンティティフレームワーク接続か他のタイプかに関係なく、2つのADO.NET接続の使用に問題はありません。
独自のEntityConnectionを管理し、このEntityConnectionをObjectContextに渡すことで、分散トランザクションの使用を回避できます。そうでなければこれらをチェックしてください。
http://forums.Microsoft.com/MSDN/ShowPost.aspx?PostID=580828&SiteID=1&mode=1http://forums.Microsoft.com/msdn/showpost.aspx? postid = 113669&siteid = 1&sb = 0&d = 1&at = 7&ft = 11&tf = 0&pageid = 1
EntityConnection conn = new EntityConnection(ConnectionString);
using (TransactionScope ts = new TransactionScope())
{
using (DatabaseEntityModel o = new DatabaseEntityModel(conn))
{
var v = (from s in o.Advertiser select s).First();
v.AcceptableLength = 1;
}
//-> By commenting out this section, it works
using (DatabaseEntityModel o = new DatabaseEntityModel(conn))
{
//Exception on this next line
var v = (from s1 in o.Advertiser select s1).First();
v.AcceptableLength = 1;
}
//->
ts.Complete();
}
ファイアウォールとサーバーの両方のファイアウォール例外にC:\ Windows\msdtc.exeを追加します。私はこれを行う前に、特定のポート番号と範囲を開放することを何回もやってみました。
昨日この問題をデバッグしている同僚と3時間過ごしたので、ここにこれを貼り付けておきます。これを取り巻くすべての答えは、これは常にファイアウォールの問題であると述べています。しかし、私たちの場合はそうではありませんでした。うまくいけば、これは他の誰かの痛みを免れるでしょう。
現在の状況は、現在Entity Frameworkに移行中です。つまり、単一のトランザクション内でnew SqlConnection(connectionString).Open()
を使用して直接、およびEFデータコンテキストを使用して間接的に接続が開かれるコードの一部があります。
これは私たちのアプリケーションでしばらくうまく機能していましたが、本番環境で機能するコードをさかのぼってテストを開始すると、EFオブジェクトが初めて接続を試みたときに、テストランナーから実行されたコードがこのエラーをスローし続けましたデータベースへ変更後同じトランザクションで直接接続が行われました。
バグの原因は結局、接続文字列にApplication Name=
引数を指定しない場合、Entity FrameworkがデフォルトでEntityFrameworkMUF
のようなものを追加することにありました。これは、接続プールに2つの異なる接続があることを意味します。
Application Name=
引数なしで手動で開いたものApplication Name=EntityFrameworkMUF
また、1つのトランザクション内で2つの異なる接続を開くことはできません。量産コードはアプリケーション名を指定しました。したがって、うまくいきました。テストコードはしませんでした。 Application Name=
引数を指定すると、バグが修正されました。
ところで、このような明示的なトランザクションを使用する場合は、SaveChanges(false)をAcceptChanges()と組み合わせて使用することを検討してください。
そうすることで、SaveChanges(false)で何かが失敗した場合、ObjectContextは変更を破棄していないため、後で再適用したり、エラーロギングなどを行うことができます。
詳細については、この投稿を参照してください: http://blogs.msdn.com/alexj/archive/2009/01/11/savechanges-false.aspx
乾杯
アレックス
問題は、2つの異なるDataContextが2つの異なる接続を効果的に作成することです。
その場合、トランザクションは分散トランザクションに昇格する必要があります。あなたの問題は、サーバーまたはクライアントでのMS DTC(Microsoft分散トランザクションコーディネーター)の構成に起因すると思います。たとえば、MSDTCのリモート接続を許可するようにサーバーが構成されていない場合、そのような例外が発生します。
たとえば、MSDTCの問題のトラブルシューティングについては このMSページ を参照できます。Googleには記事/フォーラムの質問が満載です。
さて、それは何か他のものかもしれませんが、それは本当にそれがMSDTC問題であるように聞こえます。
MQキューからメッセージを読み取って処理し、SQL 2005 Express Editionデータベースに格納するときにDTCを使用すると、同様のエラーが発生しました。 2005年かそれともExpress Express版がこの問題を引き起こしたのかを最後まで調査する時間はありませんが、2008 Standardに切り替えると、その特定の動作が消えてしまいました。