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

2024-04-19

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

我正在使用DropCreateDatabaseIfModelChanges初始化程序。当我将其更改为MigrateDatabaseToLatestVersion一切正常,但我想坚持使用以前的初始化程序。

我收到的错误是:

系统.InvalidOperationException: 系统.InvalidOperationException: 支持“AppContext”上下文的模型自 数据库已创建。考虑使用 Code First 迁移来更新 数据库(http://go.microsoft.com/fwlink/?LinkId=238269 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>

嗯,看起来 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) { }
}

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐