使用Code-First更新数据库时出错:"数据库中已经有一个名为'something'的对象."

Nur*_*rul 2 vb.net ef-code-first sql-server-2012 asp.net-web-api visual-studio-2015

我正在使用Visual Studio 2015中的Code-First进行数据库迁移.在此过程中,我已完成迁移步骤,直到添加迁移.

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

Database.SetInitializer(New MigrateDatabaseToLatestVersion(Of DbContext1, Migrations.Configuration))
Run Code Online (Sandbox Code Playgroud)

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

"Add-Migration initial -Force"
Run Code Online (Sandbox Code Playgroud)

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

"Update-Database"
Run Code Online (Sandbox Code Playgroud)

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

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

添加

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

数据库中已经有一个名为"something"的对象.

我看到了一个建议执行的答案线程

Add-Migration Initial -IgnoreChanges
Run Code Online (Sandbox Code Playgroud)

其次是

Update-Database -verbose
Run Code Online (Sandbox Code Playgroud)

我试过了两个但它仍然显示相同的错误.

Dia*_*ana 9

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

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

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

public class MyDbContext : DbContext
{
    public MyDbContext() : base("MyConnectionStringName") { ... }
    ...
}
Run Code Online (Sandbox Code Playgroud)

在您的.config文件中:

<configuration>
  ...
  <connectionStrings>
    <add name="MyConnectionStringName" connectionString="..." />
  </connectionStrings>
</configuration>
Run Code Online (Sandbox Code Playgroud)

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

Update-Database -ConnectionString <your connection string here> -ConnectionProviderName System.Data.SqlClient
Run Code Online (Sandbox Code Playgroud)

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

Update-Database -ConnectionStringName MyConnectionStringName
Run Code Online (Sandbox Code Playgroud)

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

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

每个迁移都有一个方法Up和一个方法Down.当你运行时Update-Database,总会有两个隐含参数:SourceMigrationTargetMigration.EF逐步应用Up所有迁移的方法SourceMigrationTargetMigration(或者Down如果要降级数据库的方法).未指定SourceMigrationTargetMigration参数时的默认方案SourceMigration是应用于数据库的最后一次迁移,TargetMigration是最后一次挂起的迁移.EF通过查询__MigrationsHistory项目的默认数据库表来确定这些参数,因此如果该数据库不处于一致状态,则可能会错误地生成迁移.我认为这是造成问题的原因.

因此,每次运行Update-DatabaseEF查看__MigrationsHistory表时都要知道必须运行哪些迁移,具体取决于数据库的状态,并且在执行迁移的SQL之后,每个应用的迁移都会在该表中插入新记录.

似乎在某些时候你的数据库__MigrationsHistory内容搞砸了.它在运行时发生Update-Database,Add-Migrations没有遵循正确的顺序并使用-force参数.

我的建议是解决您的问题:从头开始:删除数据库,删除迁移文件,生成新的干净Initial迁移Add-Migration Initial,只运行一次Update-Database.从那时起,每次更改模型代码时,都会生成一个新的增量迁移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 .

有关生成和运行迁移的更多信息,请访问此处.

祝好运!

  • 非常感谢您的见解。我没有删除我的数据库。我尝试只从 Migrations 文件夹中删除“初始”文件,而不是整个文件夹。然后我做了“添加迁移初始”和“更新数据库”。它现在起作用了! (2认同)