C# 支持';EFDbContextProxy';上下文已更改-测试缓存?

C# 支持';EFDbContextProxy';上下文已更改-测试缓存?,c#,entity-framework,C#,Entity Framework,我对一个实体进行了更改,运行了迁移并更新了数据库。 然后我重新运行了一个测试,它抛出了一个错误: 自创建数据库以来,支持“EFDbContextProxy”上下文的模型已更改。考虑使用代码第一迁移来更新数据库 如果我运行应用程序,我不会得到这个错误。我的EFDbContextProxy(不管是什么)似乎正在使用数据结构的旧缓存 有没有办法解决这个问题 以下是我在测试中准备db上下文的方法: public class EFFieldViewerRepository_Setup { prot

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

自创建数据库以来,支持“EFDbContextProxy”上下文的模型已更改。考虑使用代码第一迁移来更新数据库

如果我运行应用程序,我不会得到这个错误。我的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 );
        ...
    }
public类effeeldViewerRepository\u设置
{
保护日期时间现在;
受保护的模拟上下文;
受保护的EFFieldViewerRepository字段ViewerRepository;
受保护的IDbSet fieldViewerDbSet;
public EFFieldViewerRepository_设置()
{
this.now=DateTime.now;
this.mockDbContext=new Mock(){CallBase=true};
this.fieldViewerRepository=new-effeldviewerrepository(this.mockDbContext.Object);
...
}

这是我的堆栈跟踪:

我必须创建一个MockEFDbContext并扩展EFDbContext。在构造中,我运行
数据库。SetInitializer(null)

来源:
-
-

LocalDB数据库可能是罪魁祸首(我知道这听起来很奇怪) 如果实体框架被配置为生成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测试设置与@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);
}
私有模拟集;
私人模拟语境;
私人模型服务(ModelService);;
[NUnit.Framework.SetUp]
公共作废设置()
{
_set=newmock();
_set.Reset();
_context=newmock();
_Reset();
_Setup(m=>m.OutgoingEntries).Returns(_set.Object);
_Setup(m=>m.Set())。返回(_Set.Object);
_服务=新的支出服务(_context.Object);
}
神秘的代理类和LocalDB 在上面的示例中,
\u context.Object
Castle.Proxies.MyContextProxy
的一个实例。这是在运行时生成的,以允许Moq重写方法和属性。但是,如果按上面的配置EF,代理类的生成仍将触发数据库初始化。这最终会导致数据库初始化例如:

无意中破坏事物,然后笨拙地修复它们 当我添加新迁移时,上面的所有细节对我来说都或多或少是透明的。不幸的是,这导致了原始问题中提到的确切错误。为了解决根本问题,我只是删除了由Moq/Castle创建的LocalDB文件。这比听起来更复杂。我发现这些特定步骤在Windows 10上有效

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

是否在所有实体上尝试了
刷新
?能否提供堆栈跟踪?我已经添加了测试堆栈trace@derape-如何执行“刷新”
<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>
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);
}