【问题标题】:Error when Update-Database using Code-First: "There is already an object named 'something' in the database."使用 Code-First 更新数据库时出错:“数据库中已经有一个名为 'something' 的对象。”
【发布时间】:2016-11-15 09:23:22
【问题描述】:

我正在使用 Visual Studio 2015 中的 Code-First 进行数据库迁移。在此过程中,我已经完成了迁移步骤,直到 Add-Migration 。

添加迁移后,我添加了这行代码

Database.SetInitializer(New MigrateDatabaseToLatestVersion(Of DbContext1, Migrations.Configuration))

在我的 DbContext 构造函数中设置数据库初始化程序,因为我之前错过了这一步。之后,我执行了

"Add-Migration initial -Force"

在包管理器控制台中,因为我担心在添加迁移过程中需要这部分。然后,我直接执行了

"Update-Database"

问题是在我这样做之后,出现了一个错误

此操作需要连接到“主”数据库。无法创建到“主”数据库的连接,因为原始数据库连接已打开并且凭据已从连接字符串中删除。提供一个未打开的连接。

添加

重新启动计算机后,当我执行“更新数据库”时,上述错误不再出现。反而出现了另一个错误:

数据库中已经有一个名为“某物”的对象。

我看到一个回答线程建议执行

Add-Migration Initial -IgnoreChanges

紧随其后

Update-Database -verbose

我都试过了,但仍然显示相同的错误。

【问题讨论】:

    标签: vb.net asp.net-web-api visual-studio-2015 sql-server-2012 ef-code-first


    【解决方案1】:

    为了能够解决您的问题,您应该了解 EF 如何处理连接字符串以及迁移的工作原理。

    EF 如何处理连接字符串:通常您的DbContext 有一个无参数构造函数,它使用硬编码的连接字符串名称调用其基类构造函数。您的项目 app.configweb.config 文件应包含一个 connectionStrings 部分,该部分定义了具有该名称的连接字符串。 这是您的项目中使用的默认连接字符串,当您没有为包管理器控制台命令显式提供连接字符串参数时。

    一些带有连接字符串名称MyConnectionStringName的示例代码:

    public class MyDbContext : DbContext
    {
        public MyDbContext() : base("MyConnectionStringName") { ... }
        ...
    }
    

    在您的.config 文件中:

    <configuration>
      ...
      <connectionStrings>
        <add name="MyConnectionStringName" connectionString="..." />
      </connectionStrings>
    </configuration>
    

    如果您不使用该方法,您仍然可以在包管理器控制台中手动将正确的连接字符串作为参数提供给 Update-Database,如下所示:

    Update-Database -ConnectionString <your connection string here> -ConnectionProviderName System.Data.SqlClient
    

    您还可以使用您在.config 文件中定义的任何连接字符串名称:

    Update-Database -ConnectionStringName MyConnectionStringName
    

    现在关于迁移的工作原理:迁移是代码文件。每次运行Add-Migration 时,都会生成/更新一个代码文件,通常位于项目内名为Migrations 的文件夹中。迁移文件的名称由其生成时间戳和运行Add-Migration 时使用的名称组成。您可以检查这些文件的内容并查看运行Add-Migration 的效果。您还可以在生成它们后对其进行修改,然后添加自己的代码,尽管目前您不需要这样做。

    迁移是增量的。您从Initial 迁移开始,每次更改模型代码时都会生成一个新的迁移文件。该数据库包含一个名为 __MigrationsHistory 的表,用于跟踪您的数据库中运行了哪些迁移。

    每个迁移都有一个方法Up 和一个方法Down。当你运行Update-Database 时,总是有两个隐式参数:SourceMigrationTargetMigration。 EF 以增量方式应用 SourceMigrationTargetMigration 之间所有迁移的 Up 方法(如果您正在降级数据库,则使用 Down 方法)。未指定SourceMigrationTargetMigration 参数时的默认情况是SourceMigration 是应用于数据库的最后一个迁移,TargetMigration 是最后一个未决迁移。 EF 通过查询项目默认数据库的__MigrationsHistory 表来确定这些参数,因此如果该数据库处于不一致的状态,则可能会错误地生成迁移。我认为这是导致您的问题的原因。

    因此,每次运行 Update-Database 时,EF 都会查看 __MigrationsHistory 表以了解必须运行哪些迁移,具体取决于数据库的状态,并且在执行迁移的 SQL 后,会在其中插入一条新记录每个应用迁移的表。

    似乎在某些时候您的数据库__MigrationsHistory 内容搞砸了。当运行 Update-DatabaseAdd-Migrations 时没有遵循正确的顺序并使用 -force 参数时会发生这种情况。

    解决问题的建议:从头开始:删除数据库,删除迁移文件,使用Add-Migration Initial 生成新的干净Initial 迁移,使用@987654364 仅运行一次@。从那时起,每次更改模型代码时,您都会使用 Add Migration YourNewMigrationName 生成一个新的增量迁移,每次使用不同的名称,并通过运行一次 Update-Database 来应用新的迁移。

    注意:除了增量迁移之外,如果您对迁移的工作方式有足够的了解,您也可以只使用一个 Initial 迁移,并在模型代码更改时通过执行 Add-Migrations Initial -force 来更新它。 -force 参数确保不会生成新的迁移文件,而是覆盖现有的Initial 迁移文件。这种方法在开发阶段很方便,但在生产中通常不是一个好方法,因为您可能希望每次部署新版本的代码时都以增量方式运行数据库更新(您可能无法删除数据库并重新创建它,您还需要维护您的数据并确保在更新数据库时不会丢失数据。

    迁移是由 EF 生成的用于创建和更新数据库的代码文件。当您运行Update-Database 时,迁移将转换为针对您的数据库执行的 SQL。如果您想查看为特定迁移生成的确切 SQL,可以运行 Update-Database -Script -SourceMigration SomeMigration -TargetMigration SomeOtherMigration。该命令不会修改数据库,只是生成并显示将在真正的Update-Database 执行中应用的 SQL。

    更多关于生成和运行迁移的信息可以在here找到。

    祝你好运!

    更新:此答案适用于 EF6。请注意,在使用 EF Core 的 EF6 之后,情况发生了一些变化。此答案中解释的基本概念是相同的,但包管理器控制台命令发生了变化,EF 处理数据库上下文快照和迁移的方式也发生了变化。

    【讨论】:

    • 非常感谢您的见解。我没有删除我的数据库。我尝试从 Migrations 文件夹中删除“初始”文件,而不是整个文件夹。然后我做了“添加迁移初始”和“更新数据库”。它现在工作了!
    • 对不起,我有一个关于代码优先的问题。你能帮我看看here吗?
    • 你能看看我的问题here吗?我会很感激的
    • 嗨我已经按照你的方式工作了,但是当我将我的代码部署到天蓝色时它不会再次工作,说对象已经存在。还有其他方法可以检查吗?谢谢
    • @Dev 我已经成功地使用了这种方法来部署到 Azure 的数据库,所以这应该不是问题。有几个变量可能导致错误。您使用的是 EF6 还是更高版本?哪个版本的 .NET?你得到哪个确切的错误?您何时收到此错误,在部署时执行迁移时,在尝试从包管理器控制台执行迁移时?您使用哪种数据库初始化策略?我建议您创建一个单独的问题,提供更多详细信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-12
    • 2011-03-29
    • 2016-04-08
    • 2014-08-01
    • 2010-11-12
    • 2021-05-10
    相关资源
    最近更新 更多