web-dev-qa-db-ja.com

EF Database First MVC5を使用したASP.NET ID

Database FirstおよびEDMXで新しいAsp.net Identityを使用することはできますか?または、最初にコードを使用する場合のみ?

私がやったことは次のとおりです。

1)新しいMVC5プロジェクトを作成し、新しいIDでデータベースに新しいユーザーテーブルとロールテーブルを作成しました。

2)次に、関連する他のテーブルがあるため、Database First EDMXファイルを開き、新しいIdentity Usersテーブルにドラッグしました。

3)EDMXを保存すると、Database First POCOジェネレーターはユーザークラスを自動的に作成します。ただし、UserManagerとRoleManagerは、新しいIdentity名前空間(Microsoft.AspNet.Identity.IUser)から継承するUserクラスを想定しているため、POCO Userクラスの使用は機能しません。

可能性のある解決策は、POCO生成クラスを編集して、UserクラスをIUserから継承させることですか?

または、ASP.NET IdentityはCode First Designとのみ互換性がありますか?

++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++

更新:以下のAnders Abelの提案に従って、これが私がしたことです。それはうまくいきますが、もっとエレガントな解決策があるかどうか疑問に思っています。

1)自動生成されたエンティティと同じネームスペース内に部分クラスを作成することにより、エンティティのUserクラスを拡張しました。

namespace MVC5.DBFirst.Entity
{
    public partial class AspNetUser : IdentityUser
    {
    }
}

2)DBContextではなくIdentityDBContextから継承するようにDataContextを変更しました。 EDMXを更新し、DBContextクラスとEntityクラスを再生成するたびに、これをこれに戻す必要があることに注意してください。

 public partial class MVC5Test_DBEntities : IdentityDbContext<AspNetUser>  //DbContext

3)自動生成されたUserエンティティクラス内で、次の4つのフィールドにオーバーライドキーワードを追加するか、これらのフィールドはIdentityUserから継承されるため、これらのフィールドをコメント化する必要があります(ステップ1)。 EDMXを更新し、DBContextクラスとEntityクラスを再生成するたびに、これをこれに戻す必要があることに注意してください。

    override public string Id { get; set; }
    override public string UserName { get; set; }
    override public string PasswordHash { get; set; }
    override public string SecurityStamp { get; set; }
87
Patrick Tran

POCOおよびDatabase FirstでIDシステムを使用することは可能ですが、いくつかの調整を行う必要があります。

  1. POCO生成用の.ttファイルを更新して、エンティティクラスpartialを作成します。これにより、別のファイルで追加の実装を提供できるようになります。
  2. 別のファイルにUserクラスの部分的な実装を作成します

partial User : IUser
{
}

これにより、Userクラスは、実際に生成されたファイルに触れることなく、適切なインターフェースを実装します(生成されたファイルを編集することは常に悪い考えです)。

16
Anders Abel

私の手順は非常に似ていますが、共有したかったです。

1)新しいMVC5プロジェクトを作成する

2)新しいModel.edmxを作成します。新しいデータベースであり、テーブルがない場合でも。

3)web.configを編集し、この生成された接続文字列を置き換えます:

<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-SSFInventory-20140521115734.mdf;Initial Catalog=aspnet-SSFInventory-20140521115734;Integrated Security=True" providerName="System.Data.SqlClient" />

この接続文字列で:

<add name="DefaultConnection" connectionString="Data Source=.\SQLExpress;database=SSFInventory;integrated security=true;" providerName="System.Data.SqlClient" />

その後、アプリケーションをビルドして実行します。ユーザーを登録すると、テーブルが作成されます。

13
JoshYates1980

EDIT:MVC5 CodePlex Project TemplateのEF Database Firstを使用したASP.NET Identity


既存のデータベースを使用し、ApplicationUserとの関係を作成したかった。これはSQL Serverを使用して行った方法ですが、おそらく同じアイデアがどのDBでも機能します。

  1. MVCプロジェクトを作成する
  2. Web.configのDefaultConnectionの下にリストされているDBを開きます。呼び出されます(aspnet- [timestamp]またはそのようなもの)。
  3. データベーステーブルのスクリプトを作成します。
  4. スクリプトテーブルをSQL Server Management Studioの既存のデータベースに挿入します。
  5. 関係をカスタマイズしてApplicationUserに追加します(必要な場合)。
  6. 新しいWebプロジェクトの作成> MVC> DB Firstプロジェクト> EFでDBをインポート...挿入したIDクラスを除外します。
  7. IdentityModels.csで、プロジェクトのDbContextを使用するようにApplicationDbContext :base("DefaltConnection")を変更します。

編集:Asp.Net Identity Class Diagram enter image description here

10
stink

IdentityUserは、認証のためにUserStoreによって使用されるコード優先オブジェクトであるため、ここでは価値がありません。独自のUserオブジェクトを定義した後、IUserクラスで使用されるUserManagerクラスを実装する部分クラスを実装しました。 Idsを文字列ではなくintにしたかったため、UserIDのtoString()を返すだけです。同様に、nUsernameを大文字にしないことを望みました。

public partial class User : IUser
{

    public string Id
    {
        get { return this.UserID.ToString(); }
    }

    public string UserName
    {
        get
        {
            return this.Username;
        }
        set
        {
            this.Username = value;
        }
    }
}

IUserは必要ありません。 UserManagerによって使用されるインターフェイスのみです。したがって、別の「IUser」を定義する場合は、このクラスを書き直して独自の実装を使用する必要があります。

public class UserManager<TUser> : IDisposable where TUser: IUser

ここで、ユーザー、クレーム、ロールなどのすべてのストレージを処理する独自のUserStoreを作成します。コードファーストUserStoreが行うすべてのインターフェースを実装し、where TUser : IdentityUserwhere TUser : Userに変更します。あなたのエンティティオブジェクトです

public class MyUserStore<TUser> : IUserLoginStore<TUser>, IUserClaimStore<TUser>, IUserRoleStore<TUser>, IUserPasswordStore<TUser>, IUserSecurityStampStore<TUser>, IUserStore<TUser>, IDisposable where TUser : User
{
    private readonly MyAppEntities _context;
    public MyUserStore(MyAppEntities dbContext)
    { 
        _context = dbContext; 
    }

    //Interface definitions
}

以下は、いくつかのインターフェース実装の例です

async Task IUserStore<TUser>.CreateAsync(TUser user)
{
    user.CreatedDate = DateTime.Now;
    _context.Users.Add(user);
    await _context.SaveChangesAsync();
}

async Task IUserStore<TUser>.DeleteAsync(TUser user)
{
    _context.Users.Remove(user);
    await _context.SaveChangesAsync();
}

MVC 5テンプレートを使用して、AccountControllerを次のように変更しました。

public AccountController()
        : this(new UserManager<User>(new MyUserStore<User>(new MyAppEntities())))
{
}

これで、独自のテーブルでログインできるようになります。

8
Shoe

GitHubでこのプロジェクトを見てください:https://github.com/KriaSoft/AspNet.Identity

含まれるもの:

  • ASP.NET Identity 2.0のSQLデータベースプロジェクトテンプレート
  • Entity Framework Database-Firstプロバイダー
  • ソースコードとサンプル

enter image description here

も参照してください: ADO.NET IdentityのDatabase-Firstプロバイダーの作成方法

3

私はこれを数時間費やして、最終的にブログで共有した解決策を見つけました here 。基本的に、 stink の答えに記載されているすべてのことを行う必要がありますが、1つの追加事項があります。 。

要約すると、アプリケーションはIdentity Frameworkの接続文字列とアプリケーションエンティティの別の接続文字列を使用します。各接続文字列は異なるタイプです。完全なチュートリアルについては、私のブログ投稿をご覧ください。

2
Daniel Eagle

良い質問。

私はデータベース第一の人です。コードの最初のパラダイムは私にはだらしないように見え、「移行」はエラーが発生しやすいようです。

移行に煩わされることなく、aspnet IDスキーマをカスタマイズしたかったのです。私はVisual Studioデータベースプロジェクト(sqlpackage、data-dude)と、スキーマのアップグレードでそれが非常に優れた仕事をする方法に精通しています。

私の単純な解決策は次のとおりです。

1)ASPNET IDスキーマをミラーリングするデータベースプロジェクトを作成します2)このプロジェクトの出力(.dacpac)をプロジェクトリソースとして使用します3)必要に応じて.dacpacを展開します

MVC5の場合、ApplicationDbContextクラスを変更すると、これがうまくいくようです...

1)IDatabaseInitializerを実装します

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IDatabaseInitializer<ApplicationDbContext> { ... }

2)コンストラクターで、このクラスがデータベースの初期化を実装することを通知します。

Database.SetInitializer<ApplicationDbContext>(this);

3)InitializeDatabaseを実装します:

ここでは、DacFXを使用して.dacpacを展開することにしました

    void IDatabaseInitializer<ApplicationDbContext>.InitializeDatabase(ApplicationDbContext context)
    {
        using (var ms = new MemoryStream(Resources.Binaries.MainSchema))
        {
            using (var package = DacPackage.Load(ms, DacSchemaModelStorageType.Memory))
            {
                DacServices services = new DacServices(Database.Connection.ConnectionString);
                var options = new DacDeployOptions
                {
                    VerifyDeployment = true,
                    BackupDatabaseBeforeChanges = true,
                    BlockOnPossibleDataLoss = false,
                    CreateNewDatabase = false,
                    DropIndexesNotInSource = true,
                    IgnoreComments = true,

                };
                services.Deploy(package, Database.Connection.Database, true, options);
            }
        }
    }
2
Aaron Hudon

@ JoshYates1980には最も単純な答えがあることがわかりました。

一連の試行錯誤の後、Joshが提案したことを実行し、connectionStringを生成されたDB接続文字列に置き換えました。元々私が混乱していたのは、次の投稿です。

既存のデータベースにASP.NET MVC5 ID認証を追加する方法

@Winから受け入れられた回答がApplicationDbContext()接続名を変更すると述べたところ。データベース接続文字列を生成してWeb.configファイルに追加するエンティティとデータベース/モデルの最初のアプローチを使用している場合、これは少しあいまいです。

ApplicationDbContext()接続名は、Web.configファイルのデフォルト接続にmappedです。したがって、Joshの方法は最適に機能しますが、ApplicationDbContext()をより読みやすくするために、名前をデータベース名に変更して、@ Winが最初に投稿したようにして、Web.configおよびコメントの「DefaultConnection」のconnectionStringエンティティが生成したデータベースを削除または削除します。

コード例:

1
TheSchnitz

モデルクラスを保持するエンティティモデルDLLプロジェクトがあります。また、データベースプロジェクトには、すべてのデータベーススクリプトが含まれています。私のアプローチは次のとおりでした

1)最初にデータベースを使用してEDMXを持つ独自のプロジェクトを作成します

2)dbのテーブルのスクリプトを作成し、localDB(データ接続)に接続されたVS2013を使用して、スクリプトをデータベースプロジェクトにコピーし、カスタム列を追加します。 BirthDate [DATE] null以外

3)データベースを展開する

4)モデル(EDMX)プロジェクトを更新するモデルプロジェクトに追加する

5)カスタムクラスをアプリケーションクラスに追加する

public class ApplicationUser : IdentityUser
{
    public DateTime BirthDate { get; set; }
}

MVCプロジェクトにAccountControllerは次を追加しました。

アイデンティティプロバイダーは、データベースの接続文字列を1つだけ保持するために、EF接続文字列からプロバイダー文字列を抽出するために、SQL接続文字列が機能することを望んでいます

public AccountController()
{
   var connection = ConfigurationManager.ConnectionStrings["Entities"];
   var entityConnectionString = new EntityConnectionStringBuilder(connection.ConnectionString);
        UserManager =
            new UserManager<ApplicationUser>(
                new UserStore<ApplicationUser>(
                    new ApplicationDbContext(entityConnectionString.ProviderConnectionString)));
}
1
Haroon