使用Code-First更新数据库时出错:“数据库中已经有一个名为”something“的对象。 [英] Error when Update-Database using Code-First: "There is already an object named 'something' in the database."

查看:1284
本文介绍了使用Code-First更新数据库时出错:“数据库中已经有一个名为”something“的对象。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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

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

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

 添加迁移初始化-Force
pre>

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

 更新数据库

问题是在我这样做之后出现错误


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


ADDED



在我重新启动计算机之后,当我执行Update-Database时,上述错误没有出现。相反,出现了另一个错误:


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


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

 添加迁移初始-IgnoreChanges 

后跟

 更新数据库-verbose 

显示相同的错误。

解决方案

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



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



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



公共类MyDbContext:DbContext
{
public MyDbContext():base(MyConnectionStringName){...}
...
}

在您的 .config file:

 < configuration> 
...
< connectionStrings>
< add name =MyConnectionStringNameconnectionString =.../>
< / connectionStrings>
< / configuration>

如果不使用该方法,您仍然可以手动提供正确的连接字符串作为参数

  Update-数据库数据库-ConnectionString<你的连接字符串这里> -ConnectionProviderName System.Data.SqlClient 

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

 更新数据库-ConnectionStringName MyConnectionStringName 

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



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



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



所以每次运行更新数据库 EF查看 __ MigrationsHistory 表,以确定必须运行哪些迁移,具体取决于数据库的状态,并且在执行迁移的SQL后,为每个应用程序插入新记录迁移。



似乎在某些时候你的数据库 __ MigrationsHistory 内容已经搞砸了。当运行更新数据库添加迁移而不遵循正确的顺序并使用

我的建议来解决您的问题:从头开始:删除您的数据库,删除您的迁移文件,使用 Add-Migration Initial 生成一个新的干净的初始迁移,只能使用$ $ c运行一次$ C>更新的数据库的。从那时起,每次更改模型代码时,都会使用添加迁移YourNewMigrationName 生成新的增量迁移,每次使用不同的名称,并通过运行更新数据库一次。



注意:如果您对迁移的知识有足够的了解,而不是增量迁移通过执行 Add-Migrations Initial -force 初始迁移,并在模型代码更改时进行更新C>。 -force 参数确保不会生成新的迁移文件,您现有的初始迁移文件将被覆盖。这种方法在开发阶段很方便,但在生产中通常不是一个好办法,因为您可能希望在每次部署新版本的代码时逐步运行数据库更新(您可能无法删除数据库并重新创建它,并且还需要维护您的数据,并确保在更新数据库时没有数据丢失。)



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



可以找到有关生成和运行迁移的更多信息这里



祝你好运!


I'm doing database migration using Code-First in Visual Studio 2015. Along the way, i've done the migration steps up till Add-Migration .

After Add-Migration, i've added this line of code

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

in my DbContext constructor to set up Database Initializer since i missed this step previously. After that, i executed

"Add-Migration initial -Force"

in the Package Manager Console because i fear that this part is needed in the Add-Migration process. Then, i directly executed

"Update-Database"

The problem is after i did this, an error comes out

This operation requires a connection to the 'master' database. Unable to create a connection to the 'master' database because the original database connection has been opened and credentials have been removed from the connection string. Supply an unopened connection.

ADDED

After i restarted my computer, the above error didn't come out anymore when i executed 'Update-Database'. Instead, another error came out:

There is already an object named 'something' in the database.

I saw an answer thread suggesting to execute

Add-Migration Initial -IgnoreChanges

followed by

Update-Database -verbose

I've tried both but it still shows the same error.

解决方案

To be able to fix your problems you should understand how EF deals with connection strings and how migrations work.

How EF deals with connection strings: Usually your DbContext has a parameterless constructor, which calls its base class constructor with a hard-coded connection string name. Your project app.config or web.config file should contain a connectionStrings section which defines a connection string with that name. This is the default connection string used in your project when you don't explicitly provide a connection string parameter to the Package Manager Console commands.

Some example code with a connection string name MyConnectionStringName:

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

And in your .config file:

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

If you don't use that approach you still can manually provide the right connection string as a parameter to Update-Database in the Package Manager Console like this:

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

You can also use any connection string name that you have defined in your .config file:

Update-Database -ConnectionStringName MyConnectionStringName

And now about how migrations work: Migrations are code files. Every time you run Add-Migration a code file is generated/updated, usually in a folder called Migrations inside your project. The name of a migration file is composed with a timestamp of its generation concatenated with the name used when running Add-Migration. You can check the contents of those files and see the effects of running Add-Migration. You can also modify them once generated, and add your own code, though you should not need to do that by the moment.

Migrations are intended to be incremental. You start with an Initial migration, and every time you change your model code you generate a new migration file. The database contains a table named __MigrationsHistory that keeps trace of which migrations have been run in your database.

Every single migration has a method Up and a method Down. When you run Update-Database there are always two implicit parameters: SourceMigration and TargetMigration. EF incrementally applies the Up methods of all the migrations between SourceMigration and TargetMigration (or the Down methods if you are downgrading your database). The default scenario when you don't specify the SourceMigration and TargetMigration parameters is that SourceMigration is the last migration applied to the database and TargetMigration is the last of the pending ones. EF determines those parameters by querying the __MigrationsHistory table of the default database of your project, so if that database is not in a consistent state your migrations can be generated incorrectly. I think this is what is causing your problems.

So every time you run Update-Database EF looks into the __MigrationsHistory table to know which migrations must be run, depending on the state of your database, and after executing the SQL of the migrations a new record is inserted in that table for each applied migration.

It seems that at some point your database __MigrationsHistory contents got messed up. It happens when running Update-Database and Add-Migrations without following the right order and using the -force parameter.

My advice to fix your problems: Start from scratch: delete your database, delete your migration files, generate a new clean Initial migration with Add-Migration Initial, run it only once with Update-Database. From that point on, every time you change your model code you generate a new incremental migration with Add Migration YourNewMigrationName, using different names each time, and apply the new migration by running Update-Database once.

Note: Instead of the incremental migrations, if you have a good enough knowledge about how migrations work you can also use only one Initial migration and update it whenever your model code changes, by executing Add-Migrations Initial -force. The -force parameter makes sure that instead of generating a new migration file your existing Initial migration file will be overwritten. This approach comes handy at development phase, but in production usually it is not a good approach, as you probably want to run your database updates incrementally every time you deploy a new version of your code (you will probably not be able to drop your database and create it again, and also you will need to maintain your data and make sure you don't have data loss when updating your database).

Migrations are code files which are generated by EF to create and update your database. When you run Update-Database the migrations are translated to SQL which is executed against your database. If you want to see the exact SQL being generated for a specific migration you can run Update-Database -Script -SourceMigration SomeMigration -TargetMigration SomeOtherMigration. This command does not modify the database, just generates and shows the SQL that would be applied in the real Update-Database execution.

More info about generating and running migrations can be found here.

Good luck!

这篇关于使用Code-First更新数据库时出错:“数据库中已经有一个名为”something“的对象。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆