ASP.NET SimpleMembershipProvider 的自动迁移

Posted

技术标签:

【中文标题】ASP.NET SimpleMembershipProvider 的自动迁移【英文标题】:Automatic Migrations for ASP.NET SimpleMembershipProvider 【发布时间】:2012-10-25 15:34:03 【问题描述】:

所以我尝试在我的新 MVC 4 项目中使用自动迁移,但不知何故它不起作用。我一步一步followed this blog post。

我已将更改添加到 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 并不会改变任何事情。我想我错过了一些东西,但不知何故找不到什么。有什么想法吗?

【问题讨论】:

请看我在***.com/questions/26305273/…上的回答希望对您有所帮助... 【参考方案1】:

update-database -verbose 不起作用,因为在您的数据表已经存在之后您的模型已更改。

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

Add-Migration InitialMigrations -IgnoreChanges

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

update-database -verbose

现在将应用自动迁移,并且表格将随着您的更改而改变。

【讨论】:

实际上这非常有效。不幸的是,我不能给你超过 +1 和接受的答案。你为我省去了很多麻烦。再次感谢。接下来是,我应该始终使用 Add-Migration InitialMigrations 吗?或者这只是第一次。我没有找到任何关于它的在线文档。 不客气。您只需运行一次即可创建一个 InitialMigrations 类。 您通过一个简单的选项“-IgnoreChanges”解决了我为期 2 天的问题。我应该能够点击 UpVote 100000 次。 如果我收到There is already an object named 'AspNetRoles' in the database.,我应该在空白InitialMigration 文件中添加哪些更改? 这就像一个魅力。虽然我不明白为什么我需要使用 Add-Migration InitialMigrations -IgnoreChanges 创建初始迁移文件,但是当我删除我的数据库并重新创建它时。谁能解释一下?如果我添加空的初始迁移文件,我只能更新数据库。【参考方案2】:

这里发生的情况是您启用了迁移,然后运行了应用程序。通过在使用 UpdateDatabase 命令之前运行应用程序,EntityFramework 将创建并填充数据库,但由于启用迁移时数据库不存在,因此它没有创建 InitialCreate 迁移。 Migrations 仍然认为您有一个空数据库并希望创建模型中的所有对象

您可以尝试重新启用迁移,这将生成一个反映数据库当前状态的 InitialCreate 迁移。在这种情况下,我将保存您对种子方法所做的更改,而不是运行“Enable-Migrations -Force”,这应该重新创建迁移并生成 IntialCreate 迁移。然后,您可以重新填充种子方法并运行 UpdateDatabase 命令。

【讨论】:

【参考方案3】:

我有相同的排序方式。去我的本地数据库删除了 UserProfile 和其他具有外键约束的表 pages_Membership、webpages_OAuthMembership、webpages_Roles、webpages_UsersInRoles 表。当您运行 update-database -verbose 时,所有这些都会重新创建。

【讨论】:

以上是关于ASP.NET SimpleMembershipProvider 的自动迁移的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core与ASP.NET区别

ASP.NET和ASP的区别是啥?

ASP.NET 生命周期 – ASP.NET 应用生命周期

ado.net和asp.net区别?

ASP.NET开发人员需要学习ASP.NET MVC么?

ASP.NET 5 改名 ASP.NET Core 1.0