首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >EF核心迁移错误:数据库'MyDatabaseName‘已存在。选择不同的数据库名称

EF核心迁移错误:数据库'MyDatabaseName‘已存在。选择不同的数据库名称
EN

Stack Overflow用户
提问于 2018-06-22 13:08:32
回答 4查看 4.9K关注 0票数 5

我在Windows Server2016和SQL Server2017网络版上运行ASP.NET核心2.1和EF核心2.1应用程序。

Startup.cspublic void Configure(IApplicationBuilder app, ...方法的末尾,我调用了context.Database.Migrate();。这适用于迁移。

一切正常。

现在我用SQL Server2016在我的开发环境中备份数据库,将MyDatabaseName .bak文件移到服务器上,并在服务器上恢复数据库MyDatabaseName,然后重启IIS站点。

当我启动应用程序(打开浏览器)时,我得到以下错误:

应用程序启动异常: System.Data.SqlClient.SqlException (0x80131904):数据库'MyDatabaseName‘已存在。选择不同的数据库名称。

一行:context.Database.Migrate();。完全错误在底部。

如果我将MyDatabaseName更改为MyDatabaseNameX (它不存在),则创建数据库,应用所有迁移,我可以重置IIS,应用程序启动。如果我恢复数据库,我得到错误already exists

相同的应用程序(完全相同的dll)在开发和生产环境中运行应用程序。这也意味着数据库结构是相同的。

我需要在生产环境中恢复数据库。我只是不确定为什么context.Database.Migrate()会抛出错误?

完全错误:

应用程序启动异常: System.Data.SqlClient.SqlException (0x80131904):数据库'MyDatabaseName‘已存在。选择不同的数据库名称。在System.Data.SqlClient.SqlConnection.OnError(SqlException exception,Boolean breakConnection,1 wrapCloseInAction) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action1 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,Boolean async,timeout,System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource1 completion, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite, String methodName) at System.Data.SqlClient.SqlCommand.ExecuteNonQuery() at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, DbCommandMethod executeMethod, IReadOnlyDictionary2 parameterValues)处的布尔asyncWrite),Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationCommandExecutor.ExecuteNonQuery(IEnumerable`1 migrationCommands处的IReadOnlyDictionary2 parameterValues) at Microsoft.EntityFrameworkCore.Migrations.MigrationCommand.ExecuteNonQuery(IRelationalConnection connection, IReadOnlyDictionary2 parameterValues),在Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator.Create()处的Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String连接)在Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.Migrate(DatabaseFacade databaseFacade处)在MyProject.Startup.Configure(IApplicationBuilder app,AppUserManager userManager,在C:\GitLab-Runner\builds\7cab42e4\0\web\MyProject\Startup.cs:line 582中的IServiceProvider serviceProvider) -来自之前抛出异常的位置的堆栈跟踪的结束-在Microsoft.AspNetCore.Hosting.Internal.AutoRequestServicesStartupFilter.<>c__DisplayClass0_0.b__0(的Microsoft.AspNetCore.Hosting.ConventionBasedStartup.Configure(IApplicationBuilder应用)在Microsoft.AspNetCore.Server.IISIntegration.IISSetupFilter.<>c__DisplayClass4_0.b__0(IApplicationBuilder应用在Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication() ClientConnectionId:7f6b84a3-e0ea-42c7-947d-a9cafdaffbfa错误号:1801,IApplicationBuilder builder),状态:3,类:16托管环境:生产内容根路径: C:\WWW\MyProject正在侦听:http://127.0.0.1:24830应用程序已启动。按Ctrl+C键关闭。应用程序正在关闭...

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2018-07-17 23:14:55

这是一个令人讨厌的问题。数据库确实存在(我确实恢复了它),但问题是数据库的备份所有者也被转移了。

服务器上不存在本地主机上的所有者用户。所以迁移没有找到数据库(因为它没有访问权限),所以它会尝试创建一个新的数据库。

票数 7
EN

Stack Overflow用户

发布于 2018-09-30 06:30:34

在开始讨论可能的修复之前,我们需要了解一件重要的事情:迁移模式是一种很好的方法,可以确保您正在处理的所有数据库(以及您将用来连接应用程序的数据库)在任何给定的环境中都具有一致和最新的结构-测试、阶段、生产、灾难恢复等等;如果您选择使用它,您可以做的最好的事情就是坚持使用该模式的最佳实践,并确保在需要的时候调用Migrate()方法。

也就是说,您可能仍然希望在第一次运行时仅使用Migrate()方法来创建数据库,而不必以编程方式(和自动)跟踪任何进一步的迁移。如果这就是您正在经历的场景,那么您可以做的最好的事情就是将Migrate()方法包装在一个条件块中,如下所示:

代码语言:javascript
复制
if (!dbContext.Database.GetService<IRelationalDatabaseCreator>().Exists())
{
    var host = BuildWebHost(args);
    using (var scope = host.Services.CreateScope())
    {
        var dbContext = scope.ServiceProvider.GetService<ApplicationDbContext>();
        var roleManager = scope.ServiceProvider.GetService<RoleManager<IdentityRole>>();
        var userManager = scope.ServiceProvider.GetService<UserManager<ApplicationUser>>();

        // Create the Db if it doesn't exist and applies any pending migration.
        dbContext.Database.Migrate();

        // Seed the Db
        DbSeeder.Seed(dbContext, roleManager, userManager);
    }
    host.Run();
}

这样,您将确保仅当数据库尚不存在时才以编程方式执行Migrate()方法:这对于测试环境和/或任何其他您希望手动更新数据库的环境(例如,使用dotnet ef powershell命令)将是完美的。在测试环境中,您可以每次删除并重新创建数据库,而不必担心丢失实际数据。这对性能有好处,还可以避免来自Migrate()方法的SqlException,因为它只在没有数据库的时候运行,从而防止发现错误或过时迁移数据的机会。

如果您对Exists()方法在幕后实际做了什么感到好奇,您可以通过查看EF Core’s official GitHub repository中的SqlServer.Storage/Internal/SqlServerDatabaseCreator.cs类轻松地查看它:您将看到并没有什么真正的魔力--只是尝试打开连接,然后捕获SqlException并返回false或返回true。可能不是你希望在那里找到的最好的东西,但仍然比什么都没有好(至少它能做好这项工作)。

如果您需要更多信息,请查看the blog post that I wrote on such issue

票数 1
EN

Stack Overflow用户

发布于 2018-07-17 18:44:39

一种可能性是数据库是由其他或更早的迁移创建的。

如果数据库在列表中(不应该在列表中),您可以通过在Sql server management studio中查看来验证是否属于这种情况。然后尝试创建具有相同名称的数据库。如果你再次得到这个错误,那是因为它已经被创建了。

至于解决方案,您可以简单地等待数据库存在,这样您就可以再次迁移,但这并不总是实用的。另一种方法是尝试捕获此异常并添加重试机制。

代码语言:javascript
复制
try 
{
    // migrate
}
catch (SqlException exception) when (exception.Number == 1801)
{
    // retry
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50981005

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档