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

2024-01-07

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

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

System.InvalidOperationException:警告“Microsoft.EntityFrameworkCore.Infrastruct.ManyServiceProvidersCreatedWarning”生成错误:已创建了二十多个“IServiceProvider”实例供内部使用通过实体框架。这通常是由于将新的单例服务实例注入每个 DbContext 实例而引起的。例如,调用“UseLoggerFactory”每次都会传入一个新实例 - 请参阅https://go.microsoft.com/fwlink/?linkid=869049 https://go.microsoft.com/fwlink/?linkid=869049更多细节。这可能会导致性能问题,请考虑检查对“DbContextOptionsBuilder”的调用,这可能需要构建新的服务提供程序。通过将事件 ID“CoreEventId.ManyServiceProvidersCreatedWarning”传递给“DbContext.OnConfiguring”或“AddDbContext”中的“ConfigureWarnings”方法,可以抑制或记录此异常。

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

我已经阅读了存储库上的许多问题,并发现 EF 对各种事物进行了大量缓存,但关于该主题的文档不存在。建议是“找到导致这么多服务提供商被缓存的原因”,但我不知道要寻找什么。

那里有两个解决方法 https://github.com/dotnet/efcore/issues/16369:

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

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

我想知道的是:我有很多DbContext类型(因此IModel类型),影响服务提供商缓存?两者有关联吗? (我知道 EF 缓存IModel对于每一个DbContext,它是否还为每个提供者缓存一个服务提供者?)


服务提供者缓存纯粹基于上下文选项配置 - 上下文类型、模型等并不重要。

在 EF Core 5.0 中,密钥根据源代码 https://github.com/dotnet/efcore/blob/v5.0.13/src/EFCore/Internal/ServiceProviderCache.cs#L70 is

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 中您可以使用上述方法来检查密钥,在 6.0 中您可以使用一些静态字段来存储第一个选项实例并使用它来检查Equals下一个)。

请注意,EF Core 会缓存原始数据和之后的数据OnConfiguring看涨期权,所以它们都很重要。顺便说一句,生成警告的代码位于同一位置(类) -source https://github.com/dotnet/efcore/blob/v5.0.13/src/EFCore/Internal/ServiceProviderCache.cs#L153.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

测试期间的 EF Core 内部缓存和许多 DbContext 类型 的相关文章

随机推荐