Подтвердить что ты не робот

Как создать пользовательские дополнительные поля в UserProfile в MVC4

Я столкнулся с новой функцией ASP MVC 4, она поставляется с новой схемой db членства и новой инициализацией. В 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 не генерируются. Помогите мне, как я могу создать пользовательские поля?

4b9b3361

Ответ 1

Выработав ответ выше

В справочной системе WebSecurity.InitializeDatabaseConnection указано, что

Если вы хотите использовать таблицу базы данных, содержащую информацию профиля пользователя (имена пользователей, адреса электронной почты и т.д.), вы указываете строку подключения и имя таблицы, которые система членства использует для подключения к этой информации. Если вы не хотите использовать существующую таблицу профилей пользователей, вы можете указать, что метод InitializeDatabaseConnection() должен автоматически создавать таблицу профилей пользователя. (База данных для таблицы профиля пользователя уже должна существовать.)

Итак, если нам нужно больше полей в таблице UserProfile, нам просто нужно убедиться, что мы создаем таблицу профилей и запускаем метод InitializeDatabaseConnection после того, как таблица уже на месте.

В стандартном шаблоне проекта MVC4.0 из VS2012 я прокомментировал контроллер учетной записи

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

и переместил InitializeDatabaseConnection в первый инициализатор базы данных EF Code

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

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

убедитесь, что InitializeDatabaseConnection выполняется после того, как таблица уже установлена.

Добавлен класс UserProfile в мою первую модель кода EF

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

Ответ 2

Неразрушающая версия, основанная на ответе и комментариях IMLiviu:

Просто наткнулся на эту проблему и должен был открыть правильный способ сделать это из ответов + комментариев (+ проб и ошибок), поэтому я решил поделиться результатами, которые вы можете вырезать и вставить. Это основано на ответе IMLiviu, так что они полностью соответствуют им. Он изменяет существующие классы UserProfile и UserContext, поскольку они кажутся непосредственно совместимыми с EF as-is:

Я был в ужасе, увидев предложение, которое включало полное удаление базы данных, просто добавив несколько таблиц, чтобы после прочтения всех комментариев и создания прототипа, вот результат.

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, чтобы заставить все это работать, но параметр разрешения правой кнопки будет делать это для вас.

Дополнительные примечания:

Если вы решите (как и я) использовать для своих пользователей таблицу, отличную от UserProfile, вам нужно изменить несколько записей для соответствия.

  • В вашем классе SimpleMembershipInitializer вам необходимо ссылаться на новые имена таблиц и столбцов
  • В контроллере учетной записи и различных видах входа и регистрации вам необходимо ссылаться на новые поля модели (если имена изменены)
  • В классе UsersContext вы можете оставить имя_файла Userprofile как есть, но вам нужно изменить атрибут Table, чтобы он соответствовал вашему имени таблицы.
  • В классе UserProfile вам необходимо переименовать поля в соответствии с вашими новыми именами полей таблицы.
  • В базе данных вам нужно удалить взаимосвязь между webpages_UsersInRoles и UserProfile и добавить связь между вашей новой таблицей пользователя и webpages_UsersInRoles или старые проверки ссылочной целостности сломают вас во время выполнения. (Я настоятельно рекомендую вам удалить существующую таблицу UserProfile и проверить, что она не воссоздана, если у вас есть что-то, что осталось в вашем коде).

Ответ 3

Добавьте новую таблицу в базу данных и назовите ее User_Details или аналогичной, при создании пользователя вы сможете получить идентификатор пользователя и принудительно ввести данные в новую таблицу. Это один простой вариант.

Ответ 4

Посмотрите шаблон интернет-проекта MVC4, который поставляется с VS2012 или VS2010. Вы должны убедиться, что база данных не создана до того, как вы измените столбцы класса userprofile. вы можете добавить дополнительные свойства в свои классы POCO, а затем восстановить свою базу данных. если вы добавляете свойства после создания базы данных, пожалуйста, убедитесь, что вы используете миграции EF для добавления этих новых свойств в базу данных

Ответ 5

Конечно, вы, наверное, знаете, что вы должны сделать свой RegisterModel идентичным UserProfile 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 
   }

Затем я использую Packet Manager Console этими тремя легко запоминающимися командами:

  • Enable-Миграция
  • Add-MigrationMigrationName
  • Обновление-База данных//будет использоваться в Configuration.cs

Я согласен с TrueBlueAussie, и я бы сказал, что LazyInitialization больше не очень помогает, и вам действительно не нужно называть это так, как вы больше. В любом случае, все, что вам нужно сделать, это изменить действие "Зарегистрировать действие" в вашем контроллере учетной записи, чтобы вызвать метод следующим образом:

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

ПРИМЕЧАНИЕ. MVC5 использует OWIN