6

EF 4.1 DbContext、データベース ファーストのデータ レイヤーを使用する ASP.NET MVC3 アプリケーションがあります。アプリケーションを適応させる前にデータモデルを変更する傾向があるため、EDMX アプローチはうまく機能します。アプリケーションは、メタデータ参照を含む特別な EF 接続文字列で正常に動作します。

ただし、軟膏にはハエが 1 つあります。アプリケーションは、標準の接続文字列を必要とする ASP.NET メンバーシップとロールも使用します。メンバーシップ テーブルとその他の (EF マネージド) テーブルの両方が関係するユース ケースがいくつかあります。この 2 つは別々の接続文字列を使用するため、両方を含むトランザクションではそれらを処理するために DTS が必要です。できればその方法には行きたくありません。アプリケーションのすべての部分で同じ接続を使用したいだけです。

ただし、プレーンな接続文字列で EF を実行することはできません。誰か教えてください。

4

4 に答える 4

6

ここにはいくつかのオプションがあります。(これは長いことは承知していますが、全部読んでみてください)。そのようなトランザクションが必要な実際のシナリオを提供できると助かります。

まず、EF とメンバーシップの両方が同じ接続文字列を持っている場合、共通の接続を使用するという誤った仮定に取り組んでいます。これは時々正しいかもしれませんが、保証されていません。接続プーリングは、指定された文字列に対して同じ接続を使用しようとしますが、接続が既に使用されている場合は、2 つ目の接続が作成されます (またはプールに既に存在する 2 つ目の接続が再利用されます)。したがって、この一連の推論は、ある時点であなたを困らせるでしょう.

メンバーシップが解決するように設計されている問題の 1 つは、プラグイン可能なプロバイダー インターフェイスを持つことです。これにより、アプリケーションを変更する必要なく (またはそれを大幅に変更します)。

これらの機能をより緊密に統合することは、その利点を捨てることを意味します。それは許容できるかもしれませんが、これらのパスをたどると、基本的にデータ モデルが特定のメンバーシップ プロバイダー スキーマに密接に結び付けられることを理解する必要があります。数年前は、メンバーシップ システムが何年も変更されていなかったため、それが問題になるとは思われませんでしたが、最近、MS などは、異なるスキーマを持つ SimpleMembership や Universal Providers などの新しいメンバーシップ システムを導入しています。 .

では、Membership の主要な機能の 1 つを削除しているのに、なぜそれを使い続けるのでしょうか? さて、メンバーシップにはまだいくつかの利点があります。主なものは、安全なパスワードの暗号化/ハッシュや質問と回答の認証などの機能を含む、ユーザー管理ライブラリのすぐに使用できる完全な実装を提供することです。安全でバグのないメンバーシップ システムをゼロから作成することは簡単ではないため (最初はそう思えるかもしれませんが)、これはくしゃみをするようなことではありません。

したがって、1 つのオプションは、既存のものに基づいて独自の MembershipProvider を実装することです (SqlMembershipProvider など。Microsoft はこれらのソースを提供します)。次に、スキーマをオーバーライドして、必要なものに一致させることができますが、パスワードの暗号化などの他のすべての機能を保持します。それらを独自のスキーマに合わせてください。これにより、データ モデルへの適合性が大幅に向上します。

ただし、標準のメンバーシップ プロバイダーを使用することを選択した場合でも、できることがいくつかあります。

まず、メンバーシップ テーブルを Entity Framework モデルにマップするだけです。それらをデザイナーにドラッグ アンド ドロップするか、Code First に追加するだけです。ただし、これを行う場合は、それらを読み取り専用としてのみ使用し、メンバーシップ テーブルとテーブルの間に外部キー リレーションシップを作成しないでください。代わりに、EF クエリで手動結合を行い (作業は増えますが、より安全です)、それらをスタンドアロン テーブルとして扱います。

では、クエリの一部としてメンバーシップ テーブルのデータを更新または削除する必要がある状況についてはどうでしょうか? 率直に言って、標準のメンバーシップ テーブルを使用している場合、これが必要になる理由はほとんどないと思います。

メンバーシップ テーブルは非常にシンプルで、アプリ内のステートメントの一部として必要な実際のデータはほとんどありません。Profile プロバイダーを使用している場合を除きますが、私は決して使用しません。メンバーシップ テーブルをマップする必要がある場合は、ProfileProvider を使用するのではなく、独自のデータ テーブルを作成することをお勧めします。

トランザクションを参加させたいと思う唯一の理由は、新しいユーザーを作成するときです。ただし、これは 1 回限りのイベントであるため、DT はそれほどひどいものではない可能性があります。ただし、常に DTC を使用できるとは限りません。そのような場合、try-catch ブロックを使用して例外を処理することが最善の方法です。

別の方法としては、Membership を完全に破棄し、独自の IPrincipal と IIdentity の実装を作成して、独自のユーザー管理を作成するだけです (ただし、SqlManagementProvider ソースは適切な実装であるため、これの基礎として引き続き使用します)。

次に、ユーザー管理は別個のサブシステムの一部ではないため、他のサブシステムが何を行っているかを気にすることなく、更新と削除に安全に使用できます。

TL;DR

DT を受け入れることができない場合は、ワークフローを変更するか、try-catch-finally ステートメントで動作するようにコードを変更します (ただし、停電などでアプリ コードが突然停止した場合のロールバックは保証されません)。または、カスタムの IPrincipal と IIdentity の実装を使用します。

于 2012-09-16T21:22:13.420 に答える
2

ここで答えを見つけました: https://stackoverflow.com/a/3408209/1169670。ASP.NET メンバーシップ システムの接続文字列に "Enlist=false" を追加すると、DTC へのエスカレーションが停止しました。

ただし、このアプローチでは、メンバーシップ システムがトランザクションに参加するのを防ぐだけです。私の要件にはこれで十分でしたが、すべての場合にそうであるとは限りません。

于 2012-09-27T12:08:27.103 に答える
1

EF Codefirst ベースの asp.net ユニバーサル プロバイダーを確認する必要があります。メンバーシップ スキーマは POCO クラスおよび DBSet として公開されるため、DBSet を共通の DBContext クラスhttp://nuget.org/packages/Microsoft.AspNet.providers.coreに含めることができるはずです。

于 2012-09-16T20:43:07.567 に答える
0

EFに「プレーン」接続文字列を使用させることはできないと思います。

いくつかのアプリケーションでは、同じ通常の接続文字列と EF 接続文字列が並んでいます。

于 2012-09-13T14:53:01.710 に答える