web-dev-qa-db-ja.com

MVC4のUserProfileでカスタム追加フィールドを作成する方法

新しいASP= MVC 4機能に直面しました。新しいメンバーシップデータベーススキーマと新しい初期化が付属しています。mvc3および古いバージョンの開発者はweb.configの仕様を使用してカスタムユーザープロファイルフィールドを作成でき、しかし今、私はデフォルトのMVC 4プロジェクトのフィルタ名前空間のメソッドに直面しました:

WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);

およびユーザープロファイルテーブル:

[Table("UserProfile")]
    public class UserProfile
    {
        [Key]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public int UserId { get; set; }
        public string UserName { get; set; }
    }

ただし、InitializeDatabaseConnectionメソッドは、他の追加フィールドを生成する必要があるUserNameとUserIdのみを生成します。

私はEF codeFirstアプローチの良い経験があり、その場合、UserProfileクラスを編集しようとします:

[Table("UserProfile")]
    public class UserProfile
    {
        [Key]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public int UserId { get; set; }
        [Column]
        [Required]
        public string UserName { get; set; }
        [Column]
        [Required]
        public string FirstName { get; set; }
        [Column]
        [Required]
        public string LastName { get; set; }
    }

しかし、データベースを再生成すると、カスタムDbフィールドが生成されず、変更が表示されません。カスタムユーザーフィールドを作成するにはどうすればよいですか?

40
testCoder

上記の答えから詳しく説明する

WebSecurity.InitializeDatabaseConnectionメソッドヘルプは、

ユーザープロファイル情報(ユーザー名、電子メールアドレスなど)を含むデータベーステーブルを使用する場合は、メンバーシップシステムがその情報への接続に使用する接続文字列とテーブル名を指定します。既存のユーザープロファイルテーブルを使用しない場合は、InitializeDatabaseConnection()メソッドがユーザープロファイルテーブルを自動的に作成するように指定できます。 (ユーザープロファイルテーブルのデータベースが既に存在している必要があります。)

したがって、UserProfileテーブルにさらにフィールドが必要な場合は、プロファイルテーブルを作成し、テーブルが既に配置された後にInitializeDatabaseConnectionメソッドを実行していることを確認するだけです。

VS2012の標準MVC4.0プロジェクトテンプレートで、アカウントコントローラーをコメントアウトしました

[Authorize]
//[InitializeSimpleMembership]
public class AccountController : Controller
{

InitializeDatabaseConnectionをEF Code First Database Initializerに移動しました

public class MyDatabaseInit: DropCreateDatabaseAlways<MyDatabaseContext>
{
    protected override void Seed(MyDatabaseContext context)
    {
        SeedMembership();
    }

    private void SeedMembership()
    {
        WebSecurity.InitializeDatabaseConnection("MyDatabaseContext",
            "UserProfile", "UserId", "UserName", autoCreateTables: true);
    } 
}

テーブルが既に配置されたら、InitializeDatabaseConnectionが実行されるようにします。

EF Code FirstモデルにUserProfileクラスを追加しました

public class MyDatabaseContext : DbContext
{
    public DbSet<UserProfile> UserProfiles { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }
}

UserProfileテーブルに追加フィールドを追加しました

[Table("UserProfile")]
public class UserProfile
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }
    public string UserName { get; set; }
    public string MobilePhone { get; set; }
}

ここで必要なのは、アプリケーションの起動時にデータベース初期化戦略を設定し、データベースでクエリを呼び出して、その時点で認証/認証コードが呼び出される前に作成されることを確認することです。

protected void Application_Start()
{
   AreaRegistration.RegisterAllAreas();

   WebApiConfig.Register(GlobalConfiguration.Configuration);
   FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
   RouteConfig.RegisterRoutes(RouteTable.Routes);
   BundleConfig.RegisterBundles(BundleTable.Bundles);
   AuthConfig.RegisterAuth();

   Database.SetInitializer<MyDatabaseContext>(new MyDatabaseInit());
   new MyDatabaseContext().UserProfile.Find(1);
}
52
IMLiviu

IMLiviuの回答とコメントに基づく非破壊バージョン:

この1つの問題に出くわし、nknot回答+コメント(+試行錯誤)からそれを行う正しい方法が必要だったため、カットアンドペーストできる結果を共有すると思いました。これは、IMLiviuの回答に基づいているため、完全にクレジットされています。既存のUserProfileおよびUserContextクラスは、EFと直接互換性があるように変更されます。

すべてのコメントを読んでプロトタイプを作成した後、いくつかのテーブルを追加するだけでデータベースを完全に削除するという提案を見て、私はぞっとしました。結果は次のとおりです。

1-Webmatrixの作成を停止

メンバーシップテーブルの標準webmatrix作成を停止します([InitializeSimpleMembership]属性をコメントアウトします)。

[Authorize]
//[InitializeSimpleMembership]
public class AccountController : Controller

2-移行構成を作成する

以下のような移行構成クラスを作成します。

public class MigrationConfiguration : DbMigrationsConfiguration<UsersContext> 
{
    public MigrationConfiguration()
    {
        this.AutomaticMigrationsEnabled = true;  // This is important as it will fail in some environments (like Azure) by default
    }

    protected override void Seed(UsersContext context)
    {
        WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
    }
}

3-EF作成から複数形を削除する

AccountModel.csファイルUsersContextクラスを変更して、複数形オプション(OnModelCreatingイベントを追加)を削除します。

public class UsersContext : DbContext
{
    public UsersContext() : base("DefaultConnection")
    {
    }

    public DbSet<UserProfile> UserProfiles { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }
}

4-新しいフィールドをUserProfileに追加する

必要な追加フィールドをUserProfileに追加します。

[Table("UserProfile")]
public class UserProfile
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }
    public string UserName { get; set; }
    public string UserEmail { get; set; }  // <<<<<<<< E.G. THIS ADDED
}

5-アプリの起動時にテーブルを移行する

アプリが起動したら、データベースの初期化戦略を設定し、読み取りでトリガーします。

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        AuthConfig.RegisterAuth();

        Database.SetInitializer(new MigrateDatabaseToLatestVersion<UsersContext, MigrationConfiguration>());
        new UsersContext().UserProfiles.Find(1);
    }

もちろん、これをすべて機能させるにはさまざまなusingステートメントを追加する必要がありますが、右クリックresolveオプションを使用すると自動的に実行されます。

その他の注意事項:

(私がしたように)UserProfile以外のテーブルをユーザーに使用することに決めた場合、一致するようにいくつかのエントリを変更する必要があります。

  • SimpleMembershipInitializerクラスでは、新しいテーブル名と列名を参照する必要があります
  • アカウントコントローラーとさまざまなログインビューと登録ビューで、新しいモデルフィールドを参照する必要があります(名前が変更されている場合)
  • UsersContextクラスでは、Userprofileクラス名をそのままにすることができますが、テーブル名に一致するようにTable属性を変更する必要があります。
  • UserProfileクラスでは、新しいテーブルフィールド名に一致するようにフィールドの名前を変更する必要があります。
  • データベース内で、webpages_UsersInRolesUserProfileの関係を削除し、新しいユーザーテーブルとwebpages_UsersInRolesの関係を追加する必要があります。そうしないと、実行時に古い参照整合性チェックによって問題が発生します。 。 (既存のUserProfileテーブルを削除し、再作成されないことを確認することを強くお勧めします。コードに何かが残っている場合は)。
18
Gone Coding

データベースに新しいテーブルを追加し、User_Detailsまたは同様の名前で呼び出します。ユーザーの作成時に、ユーザーのIDを取得し、詳細を新しいテーブルに強制できます。これは1つの簡単なオプションです。

6
CR41G14

VS2012またはVS2010に同梱されているMVC4インターネットプロジェクトテンプレートをご覧ください。 userprofileクラスの列を変更する前に、データベースが作成されていないことを確認する必要があります。 POCOクラスにさらにプロパティを追加してから、データベースを再生成できます。データベースの生成後にプロパティを追加する場合は、EF移行を使用してそれらの新しいプロパティをデータベースに追加していることを確認してください

3
pranav rastogi

もちろん、あなたはRegisterModelUserProfile Modelと同一にする必要があることをおそらく知っているでしょう。私がやりたいのは、データベースを初期化する前にMigrationsを使用し、Configuration.csファイルに以下を入れることです。

    protected override void Seed(UsersContext context)
    {

        WebSecurity.InitializeDatabaseConnection(
            "DefaultConnection",
            "UserProfile",
            "UserId",
            "UserName", autoCreateTables: true);

        if (!WebSecurity.UserExists("yardpenalty"))
            WebSecurity.CreateUserAndAccount(
                "yardpenalty",
                "password",
                new
                {
                    Email = "[email protected]",
                    ImageUrl = "/Content/Avatars/yourname",
                    DateJoined = DateTime.Now
                },
                false);  
           //... rest of model.Builder stuff 
   }

次に、覚えやすい次の3つのコマンドでPacket Manager Consoleを使用します。

  1. 移行の有効化
  2. Add-Migration MigrationName
  3. Update-Database // Configuration.csからシードします

私は TrueBlueAussie に同意し、LazyInitializationはもはやあまり役に立たず、もはやあなたがやったようにそれを呼ぶ必要はないということまで行きます。とにかく、あなたがしなければならないのは、次のようにメソッドを呼び出すように、アカウントコントローラーで登録アクションを変更することです:

  WebSecurity.CreateUserAndAccount(model.UserName, model.Password, propertyValues: new { model.Email, model.ImageUrl, model.DateJoined });

注:MVC5はOWINを使用します

3
yardpenalty