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>
起订量测试设置
我的起订量测试设置类似于 @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.Object 是Castle.Proxies.MyContextProxy 的一个实例。这是在运行时生成的,以允许 Moq 覆盖方法和属性。但是,如果EF配置如上,代理类的生成仍然会触发数据库初始化。这最终会产生这样的数据库:
无心破坏,然后笨拙地修复它们
当我添加新迁移时,以上所有细节对我来说或多或少都是透明的。不幸的是,这导致了原始问题中提到的确切错误。为了解决根本问题,我只是删除了 Moq/Castle 创建的 LocalDB 文件。这比听起来更棘手。我发现这些特定步骤适用于 Windows 10。
- 以管理员身份打开 Powershell。
- 调用
SqlLocalDB.exe stop mssqllocaldb。
- 现在调用
SqlLocalDB.exe delete mssqllocaldb 此命令将有效地删除您拥有的任何 LocalDB 数据库。仅当您不关心 LocalDB mssqllocaldb 实例时才这样做。
- 删除由 Moq / Castle 创建的 mdf 和日志文件。我在我的 Windows 主目录中找到了这些。
- 在 Visual Studio 的测试运行程序中重新运行测试。