支持' EFDbContextProxy'的模型上下文已经改变 - 测试缓存?

时间:2015-07-22 13:09:36

标签: c# entity-framework

我对实体进行了更改,运行了迁移并更新了数据库。 然后我重新进行了测试并且发出错误:

  

支持' EFDbContextProxy'自创建数据库以来,上下文已更改。考虑使用Code First Migrations来更新数据库

如果我运行该应用程序,我不会收到此错误。看来我的EFDbContextProxy(无论如何)正在使用数据结构的旧缓存。

有任何想法如何解决这个问题?

这是我在测试中准备db上下文的方法:

public class EFFieldViewerRepository_Setup
{
    protected DateTime now;
    protected Mock<EFDbContext> mockDbContext;
    protected EFFieldViewerRepository fieldViewerRepository;
    protected IDbSet<FieldViewer> fieldViewerDbSet;

    public EFFieldViewerRepository_Setup()
    {
        this.now = DateTime.Now;
        this.mockDbContext = new Mock<EFDbContext>() { CallBase = true };
        this.fieldViewerRepository = new EFFieldViewerRepository( this.mockDbContext.Object );
        ...
    }

这是我的堆栈跟踪:http://pastebin.com/kAUmhi3j

2 个答案:

答案 0 :(得分:1)

我必须创建一个MockEFDbContext并扩展EFDbContext。在构造内部,我运行Database.SetInitializer<EFDbContext>(null)

public class MockEFDbContext : EFDbContext
{
    public MockEFDbContext()
    {
        Database.SetInitializer<EFDbContext>(null);
    }
}

然后我在我的测试中使用了这个新的MockEFDbContext而不是正常的:{/ p>

this.mockDbContext = new Mock<MockEFDbContext>() { CallBase = true };

<强>来源:
- http://gaui.is/how-to-mock-the-datacontext-entity-framework/
- https://msdn.microsoft.com/en-us/library/gg679461(v=vs.113).aspx

答案 1 :(得分:0)

LocalDB数据库可能是罪魁祸首(听起来很奇怪,我知道)

如果将Entity Framework配置为生成LocalDB数据库,则由Castle创建的Moq的DBContext代理类将依次创建一个LocalDB数据库,该数据库可能与最初创建数据库后添加的EF迁移不同步。我发现删除LocalDB数据库可以解决此问题,尽管可能有更好的解决方案,包括@ Jimmyt1988提供的答案。

实体框架配置

我在一个Visual Studio测试项目中使用Moq运行单元测试,该项目也具有连接到目标数据库的集成测试。因此,我最终在我的app.config中有了一个这样的节点。

<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
  <parameters>
    <parameter value="mssqllocaldb" />
  </parameters>
</defaultConnectionFactory>
<providers>
  <provider invariantName="Oracle.ManagedDataAccess.Client" type="Oracle.ManagedDataAccess.EntityFramework.EFOracleProviderServices, Oracle.ManagedDataAccess.EntityFramework, Version=6.122.18.3, Culture=neutral, PublicKeyToken=89b483f429c47342" />
  <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>

Moq测试设置

我的Moq测试设置类似于@ Jimmyt1988的

private Mock<DbSet<OutgoingEntry>> _set;
private Mock<MyContext> _context;
private ModelService<OutgoingEntry, MyContext> _service;

[NUnit.Framework.SetUp]
public void Setup()
{
    _set = new Mock<DbSet<OutgoingEntry>>();
    _set.Reset();
    _context = new Mock<MyContext>();
    _context.Reset();
    _context.Setup(m => m.OutgoingEntries).Returns(_set.Object);
    _context.Setup(m => m.Set<OutgoingEntry>()).Returns(_set.Object);
    _service = new OutgoingService(_context.Object);
}

神秘代理类和LocalDB

在上面的示例中,_context.ObjectCastle.Proxies.MyContextProxy的实例。这是在运行时生成的,以允许Moq覆盖“方法和属性”。但是,如果EF的配置如上所述,则代理类的生成仍将触发数据库初始化。最终将导致这样的数据库:

enter image description here

打破意图,然后以笨拙的方式解决问题

当我添加新迁移时,以上所有详细信息对我而言或多或少是透明的。不幸的是,这导致了原始问题中提到的确切错误。为了解决根本问题,我只是删除了Moq / Castle创建的LocalDB文件。这比听起来要棘手。我发现这些特定步骤适用于Windows 10。

  • 以管理员身份打开Powershell。
  • 调用SqlLocalDB.exe stop mssqllocaldb
  • 立即调用SqlLocalDB.exe delete mssqllocaldb 此命令将有效删除您拥有的所有LocalDB数据库。仅当您不关心LocalDB mssqllocaldb实例时才这样做。
  • 删除Moq / Castle创建的mdf和日志文件。我在Windows主目录中找到了这些。
  • 在Visual Studio的测试运行器中重新运行测试。