实体框架迁移:配置的构造函数始终调用

时间:2015-06-03 17:44:38

标签: c# entity-framework ef-migrations

我创建了一个简单的控制台应用程序,从nuget安装EntityFramework并执行命令Enable-Migrations。

以下是main的代码:

using(var ctx = new AppDbContext())
{
   var persons = ctx.Persons.ToList();
   Console.ReadKey();
}

以下是类Configuration

的代码
internal sealed class Configuration : DbMigrationsConfiguration<AppDbContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = true;
        Console.WriteLine("Configuration: Constructor");
    }

    protected override void Seed(AppDbContext context)
    {
        Console.WriteLine("Configuration: Seed");
    }
}

以下是app.config中的实体框架部分:

<entityFramework>
  <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
    <parameters>
      <parameter value="mssqllocaldb" />
    </parameters>
  </defaultConnectionFactory>
  <providers>
    <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
  </providers>
</entityFramework>

如果我运行控制台应用程序,那么将迁移Configuration类的迁移的构造函数。为什么?我没有更改数据库初始化程序。

  

更新

我现在尝试了一些数据库初始化程序,并查看是否调用了Configuration类构造函数。我的结果在这里:

public class AppDbContext : DbContext
{
    static AppDbContext()
    {
        //Database.SetInitializer<AppDbContext>(new CreateDatabaseIfNotExists<AppDbContext>());
        // ==> Configuration class constructor called

        //Database.SetInitializer<AppDbContext>(new DropCreateDatabaseIfModelChanges<AppDbContext>());
        // ==> Configuration class constructor called

        //Database.SetInitializer<AppDbContext>(new DropCreateDatabaseAlways<AppDbContext>());
        // ==> Configuration class constructor called

        Database.SetInitializer<AppDbContext>(null);
        // ==> Configuration class constructor is NOT called
    }

    public IDbSet<Person> Persons { get; set; }
}

我显式设置了数据库初始化程序,但调用了Configuration类构造函数。奇怪的行为。

1 个答案:

答案 0 :(得分:1)

如您所述,您已执行命令Enable-Migrations。那么做什么,添加一个新的迁移配置类。在运行应用程序时,此类将应用与迁移相关的类中指定的配置更改。

DatabaseInitializers是应用迁移的策略,即使您没有触及它们,仍然会实例化Configuration类的对象。

  

更新

如果您没有在代码中执行此操作,请查看您的应用程序配置文件。这可能有类似的东西:

    <contexts>
      <context type="AppDbContext, MyAssembly">
        <databaseInitializer 
type="System.Data.Entity.MigrateDatabaseToLatestVersion`2[[AppDbContext, MyAssembly], 
                             [Migrations.Configuration, MyAssembly]], EntityFramework" />  


</context>

有关详细信息,请参阅此documentation

  

更新2:

我想我找到了答案。当查看EntityFramework代码时,会清楚地显示当您的第一个linq查询实现时,databaseInitializer会被触发。在调试应用程序时查看下面捕获的调用堆栈。

Screenshot of Callstack from with in the configuration constructor

案例1 当您使用Database.SetInitializer<AppDbContext>(null);实际创建NullDatabaseInitializer<TContext>()作为默认初始化程序时,它不会执行任何操作,因此未调用Configuration。

案例2 :当您删除行Database.SetInitializer<AppDbContext>(null);时,事情开始使用提供商的默认值。在这种情况下,没有提供DatabaseInitializer的外部规范,因此EF将获得默认的初始化程序,在这种情况下为CreateIfNotExist<AppDbContext>。 然后初始化程序将尝试查找配置,并且Ofcourse它有一个配置类,因此,将实例化Configuration类并调用构造函数。

虽然我花了几个小时来搞清楚。