嗯,看起来 EF 6.0 引入了一条新规则:
“如果 DbContext 使用初始化程序并配置了迁移,则在构建模型时引发异常”。
在 EF 6 RC 之前(包括 EF 6 RC),这一点并未强制执行。烦人的部分是“迁移已配置”是由 DbMigrationsConfiguration 的实现定义的。似乎没有办法以编程方式禁用测试中的迁移 - 如果您实现了
我以与 Sebastian Piu 非常相似的方式解决了这个问题 - 我必须从测试中删除 Configuration 类,但我不能只是删除它,因为我们在主项目中使用 Migrations。啊!
这是我之前的代码:
public class MyDbContext : DbDContext, IMyDbContext
{
public IDbSet<Users> Users {get; set;}
public IDbSet<Widgets> Widgets {get; set;}
}
// Migrations are considered configured for MyDbContext because this class implementation exists.
internal sealed class Configuration : DbMigrationsConfiguration<MyDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
}
// Declaring (and elsewhere registering) this DB initializer of type MyDbContext - but a DbMigrationsConfiguration already exists for that type.
public class TestDatabaseInitializer : DropCreateDatabaseAlways<MyDbContext>
{
protected override void Seed(MyDbContext context) { }
}
当我的测试代码中初始化 DbContext 时,我遇到了 System.InvalidOperationException。由于该应用程序不使用任何初始化程序,因此像以前一样运行该应用程序没有问题。这只会破坏我的测试。
解决方案(感觉更像是针对 EF 中缺少的内容的一种解决方法)是将 Initializer 和 DbMigrationsConfiguration 分段,以便在运行时环境中只能看到一个。我希望我的测试使用初始化程序,并且我希望我的应用程序使用 DbMigrationsConfiguration。如果 DbContext 有一个接口,这可以更干净地完成,但可惜它只实现了 IObjectContextAdapter。
首先,我将 DbContext 抽象为:
public abstract class MyDbContextBase : DbContext, IMyDbContext
{
public IDbSet<Users> Users {get; set;}
public IDbSet<Widgets> Widgets {get; set;}
}
然后我派生了2个类:
public class MyDbContext : MyDbContextBase
{
public MyDbContext(string connectionStringOrName, IDatabaseInitializer<MyDbContext> dbInitializer)
: base(connectionStringOrName)
{
}
}
public class MyTestDbContext : MyDbContextBase
{
public MyTestDbContext(string connectionStringOrName, IDatabaseInitializer<MyDbContext> dbInitializer)
: base(connectionStringOrName)
{
Database.SetInitializer(dbInitializer);
}
}
MyDbContext 和 MyTestDbContext 都是 IMyDbContext,因此您现有的依赖项注入设置应该无需更改即可工作。我只测试了Spring.NET。
我的 DbMigrationsConfiguration 实现了测试未使用的派生类型:
internal sealed class Configuration : DbMigrationsConfiguration<MyDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
}
最后,初始化器的类型被移动到派生测试类类型:
public class TestDatabaseInitializer : DropCreateDatabaseAlways<MyTestDbContext>
{
protected override void Seed(MyTestDbContext context) { }
}
我可以确认我的测试正在通过,并且我的应用程序(和迁移)仍然像以前一样工作。