我似乎有一个奇怪的并发问题,我似乎没办法动手。 当我构建DbContext的实现时,我注入了我想由modelbuilder构建的实体(不必担心为什么)。这仅由我的应用程序在运行时完成一次,并且运行良好,但是当我进行集成测试数据库集成时,我只注入了InMemoryDatabase所需的测试实体。
现在,我似乎遇到了一个奇怪的问题,即需要不同实体的不同类文件中的两个单元测试似乎交叉了。
我继续运行单元测试,第一个测试将通过,但是第二个测试将失败,因为该模型中不存在TestObjectB。当我检查模型时,它说存在TestObjectA,即使没有在该测试中注入它。好像DataContext的实现是静态的并且被覆盖了......这些是上下文的不同文件和新构造函数,我不明白它们是如何交叉路径的?如果我自己运行失败的单元测试,则测试通过。
请注意,以下代码已针对您的视图进行了简化。
数据库上下文:
public class DataContext : DbContext
{
private readonly List<IEntity> _entities;
public DataContextA(List<IEntity> entities, DbContextOptions options) : base(options)
{
_entities = entities;
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
foreach (var entity in _entities)
{
modelBuilder.Entity(entity.GetType());
}
}
}
测试实现1:
[Fact]
public void CheckUniqueFieldA()
{
var options = new DbContextOptionsBuilder<DataContext>();
options.UseInMemoryDatabase(Guid.NewGuid().ToString());
using (var context = new DataContext(new List<IEntity> { new TestObjectA() }, options.Options))
{
//Do Something
}
}
测试实施2:
[Fact]
public void CheckUniqueFieldB()
{
var options = new DbContextOptionsBuilder<DataContext>();
options.UseInMemoryDatabase(Guid.NewGuid().ToString());
using (var context = new DataContext(new List<IEntity> { new TestObjectB() }, options.Options))
{
//Do Something
}
}
答案 0 :(得分:2)
原因是Alternating between multiple models with the same DbContext type文档主题中描述了EF Core模型缓存:
...模型缓存机制EF通过仅一次调用
OnModelCreating
并缓存模型来提高性能。默认情况下,EF假定对于任何给定的上下文类型,模型都是相同的。
该链接还包含如何解决该问题的示例。您需要创建IModelCacheKeyFactory
接口的自定义实现,并在ReplaceService
中使用OnConfiguring
替换默认的EF Core实现。实现应返回一个对象,该对象代表给定DbContext
实例的唯一缓存键。默认实现只是返回context.GetType()
。