他のいくつかと同様に、私は ASP.NET Identity Model First を実装しようとしました。試して、エラーを出して、発煙して、検索して解決したら、すべてうまくいきます..と思いました。
以下も参照してください。
- EF Database First MVC5 を使用した ASP.NET ID
- http://danieleagle.com/blog/2014/05/setting-up-asp-net-identity-framework-2-0-with-database-first-vs2013-update-2-spa-template/
行動方針、要約:
- 既定のプロジェクト (MVC5) を作成しました
- データベースの作成
- web.config で接続文字列を更新する
- Web サイトの実行、登録: テーブルが作成されます
- EF モデルの作成 (edmx)
- ID テーブルをインポートします (ここまでは問題ありません)。
- IdentityDbContext から継承するように xxx.Context.tt を変更しました
- データベース スクリプトを生成します (問題はここから始まります)
表示された問題を解決しました(最新のステップまで)。完全を期すために、それらについて説明します。
デフォルトの Identity コンテキストの使用
すべて正常に動作します。テーブルが作成され、登録してログインできます。ただし、これは私が望む状況ではありません。Model First アプローチを使用したいのです。
EF 接続文字列を使用して、カスタムのモデルの最初のコンテキストを使用する
Model First コンテキストを使用するように CreatePerOwinContext を変更します。
public void ConfigureAuth(IAppBuilder app)
{
app.CreatePerOwinContext(CustomModelFirstDbContext.Create);
そして、Model First コンテキストを使用するように ApplicationUserManager :
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<CustomModelFirstDbContext>()));
結果:
「/」アプリケーションでサーバー エラーが発生しました。
エンティティ タイプ ApplicationUser は、現在のコンテキストのモデルの一部ではありません。
説明: 現在の Web 要求の実行中に未処理の例外が発生しました。エラーの詳細とコード内のどこでエラーが発生したかについては、スタック トレースを確認してください。
例外の詳細: System.InvalidOperationException: エンティティ タイプ ApplicationUser は、現在のコンテキストのモデルの一部ではありません。
ソース エラー:
現在の Web 要求の実行中に未処理の例外が生成されました。例外の発生元と場所に関する情報は、以下の例外スタック トレースを使用して特定できます。
スタック トレース: [InvalidOperationException: エンティティ タイプ ApplicationUser は、現在のコンテキストのモデルの一部ではありません。]
カスタムの Model First コンテキストで「通常の」接続文字列を使用する
タイプ 'System.Data.Entity.Infrastructure.UnintentionalCodeFirstException' の例外が WebApplication1.dll で発生しましたが、ユーザー コードで処理されませんでした
追加情報: Database First および Model First 開発用の T4 テンプレートを使用して生成されたコードを Code First モードで使用すると、正しく動作しない場合があります。Database First または Model First を引き続き使用するには、実行中のアプリケーションの構成ファイルで Entity Framework 接続文字列が指定されていることを確認してください。Database First または Model First から生成されたこれらのクラスを Code First で使用するには、属性または DbModelBuilder API を使用して追加の構成を追加してから、この例外をスローするコードを削除します。
したがって、Identity を使用するにはデフォルトの Identity コンテキストが必要であり、他のすべてにはカスタムの Model First コンテキストを使用する必要があると考えました。好ましい解決策ではありませんが、許容範囲です。
- すべてを元に戻しました
- データベースから ID テーブルをインポートする
- (オプション) Model First アプローチを介して作成されたエンティティ
- 生成されたデータベース スクリプト
通常のプロジェクトとクイック サニティ チェック テスト プロジェクトの両方で、AspNetUserRoles テーブルに同じ問題があります。それがジャンクション テーブルで、EF デザイナーにインポートすると、すべて問題ありません。これは多対多の関係であるため表示されません。AspNetRole と AspNetUser の間の関連付けを調べると、適切に見えます。
デザイナーとマッピングの詳細:
ただし、SQL スクリプトを生成するときに、EF はキーを変更します。
デザイナーとマッピングの詳細:
生成された SQL スクリプト:
-- Creating table 'AspNetUserRoles'
CREATE TABLE [dbo].[AspNetUserRoles] (
[AspNetRoles_Id] nvarchar(128) NOT NULL,
[AspNetUsers_Id] nvarchar(128) NOT NULL
);
GO
EF では、デザイナーでマッピングの名前を変更することはできません ( social.msdn.microsoft.com のスレッド)。
その後、ジャンクション テーブルに間違った列が含まれているため、最初に作成されたコンテキストを使用して、新しいユーザーの作成が失敗します。
「/」アプリケーションでサーバー エラーが発生しました。
列名 'UserId' が無効です。
列名 'UserId' が無効です。
列名 'UserId' が無効です。
列名 'RoleId' が無効です。
列名 'UserId' が無効です。
説明: 現在の Web 要求の実行中に未処理の例外が発生しました。エラーの詳細とコード内のどこでエラーが発生したかについては、スタック トレースを確認してください。
例外の詳細: System.Data.SqlClient.SqlException: 列名 'UserId' が無効です。列名 'UserId' が無効です。列名 'UserId' が無効です。列名 'RoleId' が無効です。列名 'UserId' が無効です。
ソース エラー:
89 行目: {
行 90: var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };
91 行目: IdentityResult result = await UserManager.CreateAsync(user, model.Password);
92行目: if (result.Succeeded)
93行目: {
解決策は何ですか?生成されたスクリプトを変更しようとするか、Code First に移行する以外の方法はありますか?