为什么实体框架的EF迁移附加迁移步骤都需要数据库连接字符串?(Why does Entity Fra

2019-06-24 22:58发布

我试图理解和使用EF迁移(使用EF 4.3.1,代码第一次)。 为了脚手架新的变化,我不得不使用这样的命令:

Add-Migration MyMigration
   -ConnectionString "Data Source=.;Initial Catalog=mydb;" 
   -ConnectionProviderName "System.Data.SqlClient"
   -StartUpProjectName MyWebsite 
   -ProjectName MyEF.Migrations

为什么添加迁移要求连接字符串的数据? Update-Database需要之一,这是很有意义的。 但不添加迁移有它来自的DbContext和配置需要的一切?

这不仅仅是闲置奇迹,这是非常令人困惑,给它一个数据库,因为我们有一个“多租户”的事情,其中​​所需的数据库是灵活的,可以请求改变要求,更不用说在静态编译时。 所以,如果Add-Migration实际上是使用数据库的任何东西,我们有一个问题。

UPDATE:我们放弃了EF迁移和使用流利的迁移 ,而是和高兴。 这是很多,要快得多,即使只计算一个事实,即我们必须写一些东西两次(为迁移曾经为EF对象和一次),并且它没有在这个问题上讨论的问题。

Answer 1:

Add-Migration检查数据库的存在,并与之交互__MigrationHistory表。 作为@Anders亚伯提到它是用于调查未决迁移,也选择以前的模式实际上找到发生了什么变化 - 这一点,如果你在哪里自动迁移启用增加明确的迁移到解决方案就显得尤为重要。



Answer 2:

I got curious when reading your question, so I fired up a Sql Server Profiler to have a look at what's happening when add-migration is run. It does indeed connect to the database and accesses the DB to check the __MigrationHistory table.

This is also shown by the error message produced when trying to create a second code-based migration without running the first:

Unable to generate an explicit migration because the following explicit migrations are pending: [201205291928386_foo]. Apply the pending explicit migrations before attempting to generate a new explicit migration.

I think that the migrations engine uses the serialized model from the database to calculate what migration steps should be included in the new migration.

As far as I understand, the database is only used as a helper for the code generation. As long as all the various databases you use are compatible with the model in the code this shouldn't be a problem for your.

Edit

As @Ladislav Mrnka points out, a check with the database is required if mixing code-based and automatic migrations. When you scaffold up a new migration, it should include anything that has changed in your model since the last migration. If you're using automatic migrations, those are not tracked in the code. When calculating what changes to include in the migration, the last run migration is used as a base. The only way to check for that is the database - since automatic migrations might be turned on.

If you're running with only code-based migrations (which I think is the only option to keep control), then that database can be regarded as just a code generation help. As long as the model compatibility is ensured in all databases that you connect to, everything should work.



Answer 3:

OP写道:

但不添加迁移有它来自的DbContext和配置需要的一切?

否-为他人在这里提到的代码的设计部分的手动迁移(什么是通过创建add-migration )包含数据库模式的快照。

这就是说,你正在使用的连接字符串的事实等是非常奇怪的。 EF通常从的DbContext类(ES)和Web.Config中暗示它。 在一个项目中,我有一个单一的数据库和一个单一的DbContext,我创建了一个配置类,并添加手动迁移有:

add-migration

我没有通过任何其他命令行参数。 这是一个在EF 4.3.1 - 也许你正在使用CTP或一些较旧的版本,或只是误解了文档?

如果我有多个数据块或DbContexts,然后我有多个配置类和使用,例如:

add-migration -conf Log

它使用我的配置类及相关的连接字符串在Web.config中添加手动迁移该数据库/的DbContext。

下面是指用于存储日志(从主分贝分开)的简单的DbContext的较长代码例如:

namespace MyProj.Models.Log
{
    public class LogDb : DbContext
    {
        public DbSet<LogLine> LogLines { get; set; }
        public DbSet<LogTag> LogTags { get; set; }


        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        }
    }

    public LogDb()
#if DEPLOYDB
         : base("LogDeploy")
#else
         : base()
#endif
     {
     }
}

namespace MyProj.Migrations
{
    internal sealed class Log : DbMigrationsConfiguration<LogDb>
    {
        public Log()
        {
            AutomaticMigrationsEnabled = true;
        }
    }
}

在Web.Config中:

<add name="LogDb" connectionString="Initial Catalog=Log;Data Source=.\SqlExpress;Integrated Security=SSPI;MultipleActiveResultSets=true" providerName="System.Data.SqlClient" />
<add name="LogDeploy" connectionString="Initial Catalog=Log;Data Source=00.00.000.00,12345;User ID=sql;Password=xxx;Network Library=DBMSSOCN" providerName="System.Data.SqlClient" />

因此,在这个例子中,我有多个数据库,多个DbContexts。 所述LogDb使用基于是否“DBDEPLOY”在编译时被定义在Web.Config中不同的连接字符串; 如果是,它使用“LogDeploy。” 如果不是,它使用默认 - 连接字符串名称相同的类,“LogDb。” 这让我可以方便地部署DB从我的本地机器变成一台服务器,通过切换我的项目配置方面,SQL数据库机器上打开一个端口,并运行:

> update-database -conf Log

在包管理器控制台。



Answer 4:

I watched this video by Rowan Miller from march of 2014: Migrations - Under the Hood

In the video Rowan explains that the Add-Migration command performs several steps which include a component called EdmModelDiffer. The EdmModelDiffer compares the current model with a previous model from the last migration (which is embedded in the resx file of the previous migration) and then calculates the required changes to the database.

So the EdmModelDiffer component needs the database connection.

The steps described in the video are:

  1. Build current model from code
  2. Get previous model from last migration (stored as snapshot in resx file)
  3. Calculate required database changes (done by the EdmModelDiffer)
  4. Generated the new migration file

Theoretically one could presume that it would be enough to compare that current model to the model of the last migration to generate the new migration. But in the meantime other people could have performed changes in the database too. That's probably why there is also a check against the database. Without doing this, the resulting migration file would not need to be correct.


Take also a look at the second video called Migrations - Team Environments



文章来源: Why does Entity Framework's EF Migrations Add-Migration step require a database connection string?