c# - 测试期间的 EF Core 内部缓存和许多 DbContext 类型

标签 c# unit-testing entity-framework-core integration-testing ef-core-5.0

我有很多测试类,每个类都有几十个测试。我想隔离测试,所以不用大型上下文 MyDbContext , 我用 MyDbContextToTestFoo , MyDbContextToTestBar , MyDbContextToTestBaz等所以我有很多 DbContext子类。

在我使用 EF Core 5 进行的单元测试中,我遇到了 ManyServiceProvidersCreatedWarning .它们单独工作,但许多在作为一个组运行时会失败:

System.InvalidOperationException : An error was generated for warning 'Microsoft.EntityFrameworkCore.Infrastructure.ManyServiceProvidersCreatedWarning': More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. This is commonly caused by injection of a new singleton service instance into every DbContext instance. For example, calling 'UseLoggerFactory' passing in a new instance each time--see https://go.microsoft.com/fwlink/?linkid=869049 for more details. This may lead to performance issues, consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built. This exception can be suppressed or logged by passing event ID 'CoreEventId.ManyServiceProvidersCreatedWarning' to the 'ConfigureWarnings' method in 'DbContext.OnConfiguring' or 'AddDbContext'.

我不会对 DbContextOptionsBuilder 做任何奇怪的事情正如该错误所暗示的那样。我不知道如何诊断“......可能需要建立新的服务提供商”。在大多数测试中,我通常会创建一个上下文:new DbContextOptionsBuilder<TContext>().UseSqlite("DataSource=:memory:")其中 TContext是我上面提到的上下文类型之一。

我已经阅读了关于 repo 的许多问题,并发现 EF 对各种事物进行了大量缓存,但是关于该主题的文档不存在。推荐是“查找导致这么多服务提供者被缓存的原因”,但我不知道该查找什么。

有两个workarounds :

  • builder.EnableServiceProviderCaching(false)这显然对性能非常不利
  • builder.ConfigureWarnings(x => x.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning))这忽略了问题

我假设“服务提供者”是指 EF 的内部 IoC 容器。

我想知道的是:事实上我有很多 DbContext类型(以及 IModel 类型),影响服务提供商缓存?两者有关系吗? (我知道 EF 为每个 IModel 缓存一个 DbContext,它是否也为每个缓存一个服务提供者?)

最佳答案

服务提供商缓存完全基于上下文选项配置 - 上下文类型、模型等无关紧要。

在 EF Core 5.0 中, key 根据 source code

static long GetCacheKey(IDbContextOptions options) => options.Extensions
    .OrderBy(e => e.GetType().Name)
    .Aggregate(0L, (t, e) => (t * 397) ^ ((long)e.GetType().GetHashCode() * 397) ^ e.Info.GetServiceProviderHashCode());

而在 EF Core 6.0 中,关键是具有类似语义的重写 Equals 方法的选项实例。

所以您使用的选项有所不同 - 如果您正在覆盖它并修改其中的选项,则在最初或 OnConfiguring 调用之后。这是你需要弄清楚的(在 5.0 中你可以使用上面的方法来检查 key ,在 6.0 中你可以使用一些静态字段来存储第一个选项实例并使用它来检查 Equals下一个)。

请注意,EF Core 缓存原始和之后的 OnConfiguring 调用选项,因此它们都算在内。顺便说一句,生成警告的代码在同一个地方(类)- source .

关于c# - 测试期间的 EF Core 内部缓存和许多 DbContext 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70503024/

相关文章:

c# - Ping Azure 云服务

unit-testing - 覆盖 FastAPI 依赖项以进行测试的最佳方法,每个测试都有不同的依赖项

javascript - 在Jasmine单元测试中,如何强制失败回调触发失败请求的结果?

unit-testing - 无法使用 python 对图像上传进行单元测试

.net-core - ef-core 添加迁移不起作用

c# - 使用多线程与 C# 进行 OCR

c# - 使用 MVVM 的 BusyIndi​​cator

c# - 原始 SQL 查询和 Entity Framework Core

c# - 如何使用带有 clickonce 的文本文件并在更新时能够更新它?

c# - EF Core 子元素的列表和属性之间的相交返回 "ArgumentNullException"