我创建了一个简单的控制台应用程序,从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类构造函数。奇怪的行为。
答案 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会被触发。在调试应用程序时查看下面捕获的调用堆栈。
案例1 当您使用Database.SetInitializer<AppDbContext>(null);
实际创建NullDatabaseInitializer<TContext>()
作为默认初始化程序时,它不会执行任何操作,因此未调用Configuration。
案例2 :当您删除行Database.SetInitializer<AppDbContext>(null);
时,事情开始使用提供商的默认值。在这种情况下,没有提供DatabaseInitializer的外部规范,因此EF将获得默认的初始化程序,在这种情况下为CreateIfNotExist<AppDbContext>
。
然后初始化程序将尝试查找配置,并且Ofcourse它有一个配置类,因此,将实例化Configuration类并调用构造函数。
虽然我花了几个小时来搞清楚。