DropCreateDatabaseIfModelChanges EF6导致System.InvalidOperationException:支持上下文的模型已更改

Chr*_*ris 15 .net c# entity-framework entity-framework-6

迁移到Entity Framework 6后,在构建服务器上执行单元测试时出错.

我正在使用DropCreateDatabaseIfModelChanges初始化程序.当我改变它的MigrateDatabaseToLatestVersion一切正常,但我想坚持使用前初始化器.

我得到的错误是:

System.InvalidOperationException:System.InvalidOperationException:自创建数据库以来,支持"AppContext"上下文的模型已更改.考虑使用Code First Migrations更新数据库(http://go.microsoft.com/fwlink/?LinkId=238269).

哪个是正确的,它改变了,但是对于DropCreateDatabaseIfModelChanges初始化程序,它应该被重新创建.有任何想法吗?

EF在App.config中配置.这是相关部分:

<connectionStrings>
    <add name="AppContext" connectionString="Data Source=(localdb)\v11.0;Initial Catalog=my.app.unittest;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>
<entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
        <parameters>
            <parameter value="v11.0" />
        </parameters>
    </defaultConnectionFactory>
    <contexts>
        <context type="my.app.core.Data.AppContext, my.app.core">
            <databaseInitializer type="System.Data.Entity.DropCreateDatabaseIfModelChanges`1[[my.app.core.Data.AppContext, my.app.core]], EntityFramework" />
        </context>
    </contexts>
    <providers>
        <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
</entityFramework>
Run Code Online (Sandbox Code Playgroud)

Ste*_*ohr 19

好吧,看起来EF 6.0引入了一条新规则:

"如果DbContext正在使用初始化程序并且配置了迁移,则在构建模型时抛出异常".

直到并包括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) { }
}
Run Code Online (Sandbox Code Playgroud)

在我的测试代码中初始化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;}
}
Run Code Online (Sandbox Code Playgroud)

然后我派出了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);
  }
}
Run Code Online (Sandbox Code Playgroud)

MyDbContext和MyTestDbContext都是IMyDbContexts,因此您现有的依赖注入设置应该可以在不需要更改的情况下工作.我只测试了Spring.NET.

我的DbMigrationsConfiguration实现了测试不使用的派生类型:

internal sealed class Configuration : DbMigrationsConfiguration<MyDbContext>
{
  public Configuration()
  {
    AutomaticMigrationsEnabled = false;
  }
}
Run Code Online (Sandbox Code Playgroud)

最后,初始化程序的类型被移动到派生的测试类类型:

public class TestDatabaseInitializer : DropCreateDatabaseAlways<MyTestDbContext>
{
    protected override void Seed(MyTestDbContext context) { }
}
Run Code Online (Sandbox Code Playgroud)

我可以确认我的测试正在通过,我的应用程序(和迁移)仍然像以前一样工作.


Seb*_*Piu 5

升级到EF6后我发现了同样的问题.阅读Stefan的评论并且具有与他描述的相同的症状(测试从我的主项目加载Configuration类)

在我的案例中解决方案/解决方法是

  • class TestContext: MyDataContext在我的测试项目中创建新的
  • 将初始化程序更改DropCreateDatabaseAlways<MyDataContext>DropCreateDatabaseAlways<TestContext>
  • 更新/概括我创建真实上下文的位置以使用测试

我可以这样做,因为我的大部分测试只是从PersistenceTest类扩展,所以我理解如果你有一个大目录,这可能是一个很难改变.所以期待其他解决方案


luk*_*kew 3

这是因为您启用了迁移并且正在使用 DropCreateDatabaseIfModelChanges 初始值设定项。Entityframework 不支持在迁移中使用此初始值设定项。您有两个选择:

  • 禁用初始化程序

或者

  • 通过删除迁移配置来禁用迁移