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

Entity Framework Code-First Issues (таблица UserProfile SimpleMembership)

Если вы использовали ASP.NET MVC 4, вы заметите, что по умолчанию для интернет-приложения используется поставщик SimpleMembership, все это хорошо, хорошо и отлично работает.

Проблема связана с генерацией базы данных по умолчанию, у них есть POCO для UserProfile, определенной так:

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

.., который затем генерируется следующим образом:

using (var context = new UsersContext())
{
    if (!context.Database.Exists())
    {
         // Create the SimpleMembership database without Entity Framework migration schema
         ((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
    }
}

Это прекрасно работает, база данных генерируется просто отлично и работает без проблем. Однако, если я должен изменить POCO, как это, и удалить базу данных:

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

    public string FirstName { get; set; }
    public string Surname { get; set; }

    public string Country { get; set; }

    public string CompanyName { get; set; }
}

Создаются только первые 2 столбца, UserId и EmailAddress. Он работает очень хорошо по коду (говорит логин/регистрация), но, очевидно, ни одна из моих других пользовательских данных не сохраняется.

Я что-то упустил? Разумеется, он должен генерировать базу данных на основе всего объекта UserProfile.

4b9b3361

Ответ 1

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

Как оказалось, я ожидал, что ((IObjectContextAdapter)context).ObjectContext.CreateDatabase(); сделает то, что просто не делает, что создает все таблицы в базе данных, которые не существуют, или просто обновляют их, если они это делают, и они отличается.

Что на самом деле происходит, так это то, что он буквально запускает оператор CREATE DATABASE, который для меня является самой бесполезной вещью. Если вы не работаете в действительно странной среде, у вас всегда будет база данных, и она всегда будет существовать (и впоследствии создание таблицы никогда не произойдет!), Я бы предпочел не предоставлять доступ к реальным пользователям для создания базы данных в любом случае.

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

public SimpleMembershipInitializer()
{
#if DEBUG
    Database.SetInitializer<DataContext>(new DropCreateDatabaseIfModelChanges<DataContext>());
#else
    Database.SetInitializer<DataContext>(null);
#endif

    try
    {
        using (var context = new DataContext())
        {
            if (!context.Database.Exists())
            {
                ((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
            }
            context.Database.Initialize(true);
        }

        WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "EmailAddress", autoCreateTables: true);
    }
    catch (Exception ex)
    {
        throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
    }
}

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

"Тайна" за созданной таблицей UserProfile заключается в том, что WebSecurity.InitializeDatabaseConnection инициализирует таблицу, если она не существует на основе полей, которые вы передаете в нее, поэтому вместо этого был создан EmailAddress из UserName, потому что я изменил его в этом.

Ответ 2

1 - Необходимо включить миграцию, предпочтительно с EntityFramework 5. Используйте Enable-Migrations в диспетчере пакетов NuGet.

2 - Переместите

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

к вашему методу Seed в классе YourMvcApp/Migrations/Configuration.cs

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

        if (!Roles.RoleExists("Administrator"))
            Roles.CreateRole("Administrator");

        if (!WebSecurity.UserExists("lelong37"))
            WebSecurity.CreateUserAndAccount(
                "lelong37",
                "password",
                new {Mobile = "+19725000000", IsSmsVerified = false});

        if (!Roles.GetRolesForUser("lelong37").Contains("Administrator"))
            Roles.AddUsersToRoles(new[] {"lelong37"}, new[] {"Administrator"});
    }

Теперь EF5 будет отвечать за создание вашей таблицы UserProfile, после этого вы вызовите WebSecurity.InitializeDatabaseConnection, чтобы зарегистрировать SimpleMembershipProvider с уже созданной таблицей UserProfile, а также рассказать SimpleMembershipProvider, какой столбец UserId и UserName. Я также показываю пример того, как вы можете добавлять пользователей, роли и связывать их в методе Seed с пользовательскими свойствами/полями UserProfile, например. пользователя Mobile (number).

3 - Теперь, когда вы запускаете базу данных обновлений из Консоли диспетчера пакетов, EF5 предоставит вашей таблице все ваши пользовательские свойства.

Дополнительные ссылки см. в этой статье с исходным кодом: http://blog.longle.net/2012/09/25/seeding-users-and-roles-with-mvc4-simplemembershipprovider-simpleroleprovider-ef5-codefirst-and-custom-user-properties/

Ответ 3

У меня была такая же проблема. Я добавил код, чтобы миграции выполнялись непосредственно перед "CreateDatabase" в SimpleMembershipInitializer.

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

  private class SimpleMembershipInitializer
    {
        public SimpleMembershipInitializer()
        {
            Database.SetInitializer<WomContext>(null);

            // forcing the application of the migrations so the users table is modified before
            // the code below tries to create it. 
            var migrations = new MigrateDatabaseToLatestVersion<WomContext, Wom.Migrations.Configuration>();
            var context = new WomContext(); 
            migrations.InitializeDatabase(context); 

            try
            {....

Ответ 4

Если у вас нет планов вносить изменения после того, как система работает вживую, и это происходит только в процессе разработки и не стремится к миграции. Попробуйте обрезать таблицу __MigrationHistory.

truncate table __MigrationHistory