ASP.NET SimpleMembershipProvider的自动迁移

43

我尝试在我的新MVC 4项目中使用自动迁移,但不知何故它没有起作用。我逐步按照这篇博客文章进行操作。

我已经对UserProfile账户模型(添加了NotaryCode字段)进行了更改:

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

然后我在包管理器控制台上写下enable-migrations,出现了一个配置类(继承自DbMigrationsConfiguration<Web.Models.UsersContext>),然后我将该类填充如下:

public Configuration()
{
    AutomaticMigrationsEnabled = true;
}

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

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

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

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

    string adminUser = "randolf";

    if (!WebSecurity.UserExists(adminUser))
        WebSecurity.CreateUserAndAccount(
            adminUser,
            "12345",
            new { NotaryCode = -1 });

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

然后我尝试运行update-database -verbose,但是它没有起作用。我的意思是,这是输出结果:

数据库中已经存在名为'UserProfile'的对象。

PM> update-database -verbose
Using StartUp project 'Web'.
Using NuGet project 'Web'.
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
Target database is: 'VesperCloud' (DataSource: .\SQLSERVER, Provider: System.Data.SqlClient, Origin: Configuration).
No pending code-based migrations.
Applying automatic migration: 201211051825098_AutomaticMigration.
CREATE TABLE [dbo].[UserProfile] (
    [UserId] [int] NOT NULL IDENTITY,
    [UserName] [nvarchar](max),
    [NotaryCode] [int] NOT NULL,
    CONSTRAINT [PK_dbo.UserProfile] PRIMARY KEY ([UserId])
)
System.Data.SqlClient.SqlException (0x80131904): There is already an object named 'UserProfile' in the database.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async, Int32 timeout)
   at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite)
   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
   at System.Data.Entity.Migrations.DbMigrator.ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement)
   at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement)
   at System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable`1 migrationStatements)
   at System.Data.Entity.Migrations.Infrastructure.MigratorBase.ExecuteStatements(IEnumerable`1 migrationStatements)
   at System.Data.Entity.Migrations.DbMigrator.ExecuteOperations(String migrationId, XDocument targetModel, IEnumerable`1 operations, Boolean downgrading, Boolean auto)
   at System.Data.Entity.Migrations.DbMigrator.AutoMigrate(String migrationId, XDocument sourceModel, XDocument targetModel, Boolean downgrading)
   at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.AutoMigrate(String migrationId, XDocument sourceModel, XDocument targetModel, Boolean downgrading)
   at System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
   at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
   at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)
   at System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(String targetMigration)
   at System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.RunCore()
   at System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.Run()
ClientConnectionId:a7da0ddb-bccf-490f-bc1e-ecd2eb4eab04
**There is already an object named 'UserProfile' in the database.**

我知道该对象存在。我的意思是,我正在尝试使用自动迁移来精确修改并运行数据库,而无需手动重新创建。但不知何故,这并没有起作用。

我查看了MSDN文档,并找到了该属性:

AutomaticMigrationDataLossAllowed = true;

但将其设置为true并没有改变任何内容。我想我可能漏掉了什么,但是却无法找到。有任何想法吗?


请查看我在 https://dev59.com/Puo6XIcBkEYKwwoYIAkL#28316226 上的答案。希望这可以帮到你... - Murat Yıldız
3个回答

127

update-database -verbose无法正常工作,因为您的模型已在数据表创建后更改。

首先,请确保UserProfile类没有任何更改。然后运行:

Add-Migration InitialMigrations -IgnoreChanges

这将生成一个空白的“InitialMigration”文件。现在,添加任何所需的UserProfile类更改。一旦更改完成,再次运行更新命令:

update-database -verbose

现在自动迁移将被应用并且表将以您的更改进行修改。


5
实际上,这个方法完美地解决了我的问题。不幸的是,我不能给你比+1更高的评分或接受回答。你帮我省去了很多麻烦。再次感谢你。接下来的问题是,我是否应该总是使用Add-Migration InitialMigrations?还是只需要在第一次使用它即可?我在网上没有找到任何文档说明。 - Erre Efe
1
不用谢。 只需要运行一次即可创建一个InitialMigrations类。 - Nguyen Ha Minh
2
你用一个简单的选项“-IgnoreChanges”解决了我两天的问题。我应该能够点击UpVote 100000次。 - eestein
如果我得到了数据库中已经存在名为'AspNetRoles'的对象,我需要在空白的InitialMigration文件中做哪些更改? - J86
这个方法非常有效。虽然我不明白为什么需要使用Add-Migration InitialMigrations -IgnoreChanges创建初始迁移文件,当我删除并重新创建数据库时。有人能解释一下吗?只有在添加空的初始迁移文件后,我才能更新数据库。 - Archna

6
看起来你启用了迁移,然后运行了应用程序。在使用UpdateDatabase命令之前运行应用程序,EntityFramework会创建和填充数据库,但是由于在启用迁移时数据库不存在,所以它没有创建InitialCreate迁移。迁移仍然认为你有一个空的数据库,并且想要创建模型中的所有对象。
你可以尝试重新启用迁移,这将生成反映当前数据库状态的InitialCreate迁移。在这种情况下,我建议你保存对seed方法所做的更改,然后运行"Enable-Migrations -Force",这样应该重新创建迁移并生成InitialCreate迁移。然后你可以重新填充seed方法并运行UpdateDatabase命令。

0

我有同样的问题,但是采用了不同的解决方法。我去了本地数据库,删除了UserProfile和其他具有外键约束的表,包括webpages_Membership、webpages_OAuthMembership、webpages_Roles和webpages_UsersInRoles表。当你运行update-database -verbose时,所有这些表都会重新创建。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接