【问题标题】:EF Core DbContext Concurrency Issue with XUnit TestsXUnit 测试的 EF Core DbContext 并发问题
【发布时间】:2019-05-26 17:33:17
【问题描述】:

我似乎有一个奇怪的并发问题,我似乎无法解决。 当我构建 DbContext 的实现时,我注入了我想由模型构建器构建的实体(不用担心为什么)。这仅由我的应用在运行时完成一次并且运行良好,但是当我在集成测试数据库集成时,我只注入了我的 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
                }
            }

【问题讨论】:

  • 尝试将两个类放在同一个测试集合中,这样它们就不会并行运行并相互影响。
  • 嗨@AmanB,这将解决问题,但反对这一点。我不知道他们为什么会相互影响。他们不应该有任何导致他们相互影响的代码。知道为什么会这样吗?
  • docs.microsoft.com/en-us/ef/core/modeling/dynamic-model。默认情况下,OnModelCreating 绑定到上下文 type,而不是上下文 instance
  • @IvanStoev 非常感谢。我不知道“这是由 EF 使用的模型缓存机制引起的,它通过仅调用 OnModelCreating 一次并缓存模型来提高性能”如果你回答我会接受它。

标签: c# entity-framework-core xunit


【解决方案1】:

原因是Alternating between multiple models with the same DbContext type 文档主题中描述的 EF Core 模型缓存:

...EF 使用的模型缓存机制通过仅调用一次OnModelCreating 并缓存模型来提高性能。

默认情况下,EF 假定对于任何给定的上下文类型,模型都是相同的。

该链接还包含一个如何解决它的示例。您需要创建IModelCacheKeyFactory 接口的自定义实现,并在OnConfiguring 中使用ReplaceService 替换默认的EF Core 实现。实现应该返回一个对象,该对象表示给定DbContext 实例的唯一缓存键。默认实现只返回context.GetType()

【讨论】:

    猜你喜欢
    • 2019-11-25
    • 1970-01-01
    • 2017-04-25
    • 1970-01-01
    • 2018-04-19
    • 2023-01-10
    • 2018-02-20
    • 1970-01-01
    • 2018-04-21
    相关资源
    最近更新 更多