简体   繁体   English

当SQL Azure中不存在数据库时,我是否需要首先迁移EF代码?

[英]Do I need a migration for EF code first when the database does not exist in SQL Azure?

I have tried lots of variations of EF migration v6.0.1 (from no database, to empty databases to existing databases) and I have a particular problem with Azure DB instances not being able to correctly be created on first deploy using Octopus deploy. 我尝试了EF迁移v6.0.1的多种变体(从无数据库到空数据库再到现有数据库),并且遇到一个特殊问题,即Azure数据库实例无法在使用Octopus部署的第一次部署中正确创建。

There are a number of places where this could be going wrong, so I thought I would check some basics of EF Code First migration with you fine people if I may: 在很多地方这可能会出错,所以我想我可以和您一起检查一下EF Code First迁移的一些基础知识,如果可能的话:

If I create a code-first model, and know that the database does not exist in the intended target database server on Azure. 如果我创建了代码优先模型,并且知道该数据库在Azure上的预期目标数据库服务器中不存在 With the default of 'CreateDatabaseIfNotExists' approach and with AutomaticMigrations disabled; 默认为'CreateDatabaseIfNotExists'方法并且禁用了AutomaticMigrations;

If I then call 'migrate.exe' with the assembly containing my DbContext and migration Configuration will I get a new database created with the current state of the model? 如果然后使用包含我的DbContext和迁移配置的程序集调用“ migrate.exe”,是否将获得一个使用模型当前状态创建的新数据库? or will I get a new database with nothing in it? 还是会得到一个没有任何内容的新数据库? ie do I need to explicitly 'add-migration' for the initial state of the model? 即我是否需要为模型的初始状态显式地“添加迁移”?

I have read in the documentation that the database instance should be created automatically by the migration process, but no one states clearly (at least to me) that this newly created database will be generated with the current model without a formal 'initial state' migration created. 我已经阅读了文档,该数据库实例应由迁移过程自动创建,但是没有人清楚(至少对我而言)明确地说,这种新创建的数据库将在没有正式的“初始状态”迁移的情况下使用当前模型生成创建。

So the question is this: do I need an explicit migration model generated for migrate.exe to work from? 所以问题是这样的:我是否需要生成一个显式迁移模型才能使migrate.exe工作?

Through whatever means I try, I get a database but the application launches with the unfriendly message "Model compatibility cannot be checked because the database does not contain model metadata. Model compatibility can only be checked for databases created using Code First or Code First Migrations." 通过任何尝试,我都会得到一个数据库,但是应用程序启动时会显示一条不友好的消息:“无法检查模型兼容性,因为该数据库不包含模型元数据。只能为使用Code First或Code First迁移创建的数据库检查模型兼容性。 “ Remembering that this is the same application library that just created the database in the first place (from scratch) I fail to understand how this has happened! 记住,这是从头开始创建数据库的同一应用程序库,我无法理解它是如何发生的!

I did manually delete the target database a few times via SQL Server management studio, is this bad? 我确实通过SQL Server Management Studio几次手动删除了目标数据库,这不好吗? Have I removed some vital user account that I need to recover? 我是否删除了一些需要恢复的重要用户帐户?

Migrations and the Database Initializer CreateDatabaseIfNotExists are not the same . 迁移和数据库初始化程序CreateDatabaseIfNotExists 不同

Migrations uses the Database Initializer MigrateDatabaseToLatestVersion , which relies upon a special table in the database _MigrationsHistory . 迁移使用数据库初始化程序MigrateDatabaseToLatestVersion ,它依赖于数据库_MigrationsHistory的特殊表。

By contrast, CreateDatabaseIfNotExists is one of the Database Initializers which relies upon the special database table EdmMetadata . 相比之下, CreateDatabaseIfNotExists是依赖特殊数据库表EdmMetadata的数据库初始化EdmMetadata It does exactly as it implies: Creates a database with tables matching the current state of the model, ie a table for each DbSet<T> , only when the database does not exist . 它的含义完全相同: 仅当数据库不存在时才使用与模型的当前状态匹配的表(即,每个DbSet<T>的表)创建数据库。

The specific error you have quoted here, Model compatibility cannot be checked because the database does not contain model metadata. 您在此处引用的特定错误“ Model compatibility cannot be checked because the database does not contain model metadata. , occurs due to the existence of DbSet<T> objects which were added to the code base after the initial database creation, and do not exist in EdmMetadata . 的出现是由于存在DbSet<T>对象,该对象在初始数据库创建之后已添加到代码库中,并且在EdmMetadata不存在。

There are 4 basic Database Initializers available, 3 of which are for use when migrations is not being used: 共有4种基本的数据库初始化程序,其中3种在不使用迁移时使用:

  • CreateDatabaseIfNotExists
  • DropCreateDatabaseWhenModelChanges
  • DropCreateDatabaseAlways

Also note, the 4th Initializer, MigrateDatabaseToLatestVersion , will allow you to use Migrations even if AutomaticMigrations is disabled; 还要注意, 即使禁用了AutomaticMigrations ,第4个初始化程序MigrateDatabaseToLatestVersion也将允许您使用迁移。 AutomaticMigrations serves a diffierent purpose, and does not interact with the Database Initializers directly. AutomaticMigrations作用不同,并且不直接与数据库初始化程序交互。

If you intend to use Migrations, you should change the Database Initializer to MigrateDatabaseToLatestVersion and forget about the other 3. If, instead, you intend to not use Migrations, then the choice of Initializer is situational. 如果打算使用迁移,则应将数据库初始化程序更改为MigrateDatabaseToLatestVersion ,而MigrateDatabaseToLatestVersion其他3个。如果相反,您打算使用迁移程序,则根据情况选择初始化程序。

  • CreateDatabaseIfNotExists will be more appropriate when you are certain that your data model is not undergoing active change, and you only intend to be concerned with database creation on a new deployment. 当您确定数据模型没有进行活动更改并且只打算关注在新部署中创建数据库时, CreateDatabaseIfNotExists将更合适。 This Initializer will elp ensure that you do not have any issues with accidental deletion of a database or live data. 此初始化程序将确保您不会意外删除数据库或实时数据。
  • DropCreateDatabaseWhenModelChanges is most appropriate in development, when you are changing the model fairly often, and want to be able to verify these changes to the model. DropCreateDatabaseWhenModelChanges最适合在开发中使用,当您经常更改模型并希望能够验证对模型的这些更改时。 It would not be appropriate for a production server, as changes to the model could inadvertently cause the database to be recreated. 它不适用于生产服务器,因为对模型的更改可能会无意间导致重新创建数据库。
  • DropCreateDatabaseAlways is only appropriate in testing, where your database is created from scratch every time you run your tests. DropCreateDatabaseAlways仅适用于测试,每次运行测试时都从头开始创建数据库。

Migrations differs from these 3 Database Initializers, in that it never drops the database , it instead uses Data Motion to execute a series of Create Table and Drop Table SQL calls. 迁移与这3个数据库初始化程序不同,它从不删除 数据库 ,而是使用Data Motion执行一系列的Create TableDrop Table SQL调用。

You also can use Update-Database -Script -SourceMigration:0 in the Package Manager Console at any time, no matter which Database Initializer you are using, to generate a full SQL script that can be run against a server to recreate the database. 您也可以随时在Package Manager控制台中使用Update-Database -Script -SourceMigration:0 ,无论您使用的是哪种数据库初始化程序,都可以生成完整的SQL脚本,该脚本可在服务器上运行以重新创建数据库。

Firstly, many thanks to Claies who helped me get to the bottom of this problem. 首先,非常感谢Claies帮助我解决了这个问题。 I have accepted his answer as correct as ultimately it was a combination of his response and a few additional bits of reading that got me to my solution. 我接受了他的回答是正确的,因为归根结底,这是他的回答和一些额外阅读的结合,这使我获得了解决方案。

In answer to the actual posts question 'Do I need a migration for EF code first when the database does not exist in SQL Azure?' 在回答实际帖子问题“当数据库在SQL Azure中不存在时,我是否需要首先迁移EF代码?” the answer is yes you do if you have disabled automatic migrations. 如果您禁用了自动迁移,答案是肯定的。 But there is a little more to be aware of: 但是还有一点要注意:

The Azure aspects of this particular problem are actually irrelevant in my situation. 在我的情况下,此特定问题的Azure方面实际上无关紧要。 My problem was two-fold: 我的问题有两个:

  1. The migration being generated was out of sync with respect to the target model. 生成的迁移与目标模型不同步。 What do I mean? 我什么意思 I mean, that I was generating the migration script from my local database which itself was not in sync with the local codebase which created a migration that was incorrect. 我的意思是,我是从本地数据库生成迁移脚本的,而本地数据库本身与本地代码库不同步,从而导致迁移不正确。 This can be seen by comparing the first few lines of the Model text in the __MigrationHistory. 通过比较__MigrationHistory中的Model文本的前几行可以看到这一点。 This awareness was helped by referring to this helpful post which explains how it works. 通过参考此有用的帖子来解释这种工作原理,有助于提高这种意识。

  2. And more embarrassingly (I'm sure we've all done it) is that my octopus deployment of the web site itself (using Octopack) somehow neglected to include the Web.Config file. 更令人尴尬的是(我确信我们已经完成了所有工作)是我自己的网站八达通部署(使用Octopack)以某种方式忽略了Web.Config文件。 From what I can tell, this may have occurred after I installed a transform extension to Visual Studio. 据我所知,这可能是在我将转换扩展安装到Visual Studio之后发生的。 Within my nuget package I can see that there is a web.config.transform file but not a web.config. 在我的nuget包中,可以看到有一个web.config.transform文件,但没有一个web.config。 Basically this meant that when the application started up, it had no configuration file to turn to, no connections string at all. 基本上,这意味着应用程序启动时,它没有配置文件可找,根本没有连接字符串。 But this resulted in the slightly misleading error 但这导致了轻微的误导性错误

Model compatibility cannot be checked because the database does not contain model metadata. 由于数据库不包含模型元数据,因此无法检查模型兼容性。

Whereas what it should have said was, there isn't a connection string you idiot. 应该说的是,您没有白痴的连接字符串。 Hopefully this helps people understand the process a little better after reading Claies answer and also that blog-post. 希望这可以帮助人们在阅读Claies答案以及该博客文章后更好地理解该过程。 First though, check you have a web.config file and that it has a connection string in it... 不过,首先,请检查您是否有一个web.config文件,并且其中是否包含连接字符串...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM