【问题标题】:How to create custom additional fields in UserProfile in MVC4如何在 MVC4 的 UserProfile 中创建自定义附加字段
【发布时间】:2026-01-04 18:50:01
【问题描述】:

我遇到了新的 ASP MVC 4 特性,它带有新的成员数据库架构和新的初始化。在 mvc 3 和旧版本中,开发人员能够使用 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 字段。 请帮助我,如何创建自定义用户字段?

【问题讨论】:

  • 我发现的一个解决方案是手动在表中创建字段,效果很好,但我想知道有什么方法可以从代码中生成相同的字段。

标签: c# asp.net-mvc entity-framework asp.net-mvc-4 simplemembership


【解决方案1】:

根据上面的答案详细说明

WebSecurity.InitializeDatabaseConnection 方法帮助指出

如果要使用包含用户个人资料信息(用户名、电子邮件地址等)的数据库表,请指定成员资格系统用来连接到该信息的连接字符串和表名。如果您不想使用现有的用户配置文件表,您可以指定 InitializeDatabaseConnection() 方法应该自动创建用户配置文件表。 (用户配置文件表的数据库必须已经存在。)

因此,如果我们想在UserProfile 表中添加更多字段,我们只需要确保我们正在创建一个配置文件表并在该表已经就位后运行InitializeDatabaseConnection 方法。

在 VS2012 的标准 MVC4.0 项目模板中,我已经注释掉了 Account 控制器

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

并将 InitializeDatabaseConnection 移动到 EF Code First 数据库初始化程序中

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);
}

【讨论】:

  • Database System.Data.Entity.Database 还是WebMatrix.Data.Database
  • @Ciwan 您还需要通过视图填充字段。您可以使用模型绑定器扩展注册视图 - 在填充时考虑“model => model.MobilePhone”。
  • 您为什么决定使用 DropCreateDatabaseAlways 作为 DB 初始化程序?不是每次重启应用都会删除所有数据库数据吗?
  • @Shedal - 那么您可能想尝试类似:Database.SetInitializer(new MigrateDatabaseToLatestVersion());其中 Configuration : DbMigrationsConfiguration 并且有一个 Seed 方法可以覆盖。
  • +1 感谢所有有用的提示,但不幸的是留下“先删除所有内容”作为答案。我根据您的回答和最终的 cmets 构建了一个原型,并在下面添加了该原型,以便其他人可以从您的实际解决方案中受益,而不会像我刚刚经历的那样痛苦:)
【解决方案2】:

基于 IMLiviu 的答案和 cmets 的无损版本:

刚刚遇到这个问题,不得不解开从答案+ cmets(+反复试验)中正确的方法,所以我想我会分享你可以剪切和粘贴的结果.这是基于 IMLiviu 的回答,因此完全归功于他们。它修改了现有的 UserProfileUserContext 类,因为它们看起来与 EF 原样直接兼容:

看到一个涉及完全删除数据库的建议,我很震惊,只是添加了几个表,所以在阅读了所有 cmets 并创建了原型之后,结果如下。

1 - 停止创建 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 表并检查它是否被重新创建。如果是您的代码中遗留了一些东西)。

【讨论】:

  • 我在 Application_Start() 方法中遇到错误。它说:“MigrationConfiguration”不能用作泛型类型或方法“System.Data.Entity.MigrateDatabaseToLatestVersion”中的类型参数“TMigrationsConfiguration”。没有从“MigrationConfiguration”到“System.Data.Entity.Migrations.DbMigrationsConfiguration”的隐式引用转换。
  • @Josh Barber:此答案与内存中的 EF 5 一起使用。我猜你正在使用 EF 6 并且事情已经改变了(又一次)|
  • 应用启动时迁移表是每次还是第一次发生?
  • @ParthShah:它只在它们不存在时才做任何事情,所以第一次,或者在删除你的数据库表之后:)
【解决方案3】:

向数据库添加一个新表并将其命名为 User_Details 或类似名称,在创建用户时,您可以检索用户的 ID 并将详细信息强制到新表中。这是一个简单的选择。

【讨论】:

    【解决方案4】:

    查看 VS2012 或 VS2010 附带的 MVC4 互联网项目模板。 在修改 userprofile 类的列之前,您需要确保未创建数据库。您可以在 POCO 类中添加更多属性,然后重新生成数据库。 如果您在生成数据库后添加属性,请确保您使用 EF 迁移将这些新属性添加到数据库中

    【讨论】:

      【解决方案5】:

      当然,您可能知道您必须使您的RegisterModelUserProfile Model 相同。我喜欢做的是在初始化数据库之前使用迁移并将以下内容放入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 = "youremail@yahoo.com",
                          ImageUrl = "/Content/Avatars/yourname",
                          DateJoined = DateTime.Now
                      },
                      false);  
                 //... rest of model.Builder stuff 
         }
      

      然后我通过这三个好记的命令使用Packet Manager Console

      1. 启用迁移
      2. Add-Migration 迁移名称
      3. Update-Database // 将从 Configuration.cs 播种

      我同意 TrueBlueAussie 的观点,并且会说 LazyInitialization 不再很有帮助,你真的不必再像以前那样称呼它了。无论如何,您所要做的就是在您的帐户控制器中更改您的注册操作以调用这样的方法:

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

      注意:MVC5 使用 OWIN

      【讨论】:

        最近更新 更多