I'm trying to implement caching for certain methods of overridden ProductModelFactory within our plugin.
Here is the code:
public override ProductReviewsModel PrepareProductReviewsModel(ProductReviewsModel model, Product product)
{
var cacheKey = _cacheKeyService.PrepareKeyForDefaultCache(ProductReviewsCacheKeys.ProductReviewsModelByProductIdCacheKey, product.Id);
var productReviewsModelSource = _staticCacheManager.Get(cacheKey, () => base.PrepareProductReviewsModel(new ProductReviewsModel(), product));
//other code
}
The problem is that sometimes randomly we get the following error:
System.ObjectDisposedException: IDataContext is disposed, see https://github.com/linq2db/linq2db/wiki/Managing-data-connection
Object name: 'DataConnection'.
at LinqToDB.Data.DataConnection.CheckAndThrowOnDisposed()
at LinqToDB.Data.DataConnection.LinqToDB.IDataContext.GetQueryRunner(Query query, Int32 queryNumber, Expression expression, Object[] parameters)
at LinqToDB.DataContext.LinqToDB.IDataContext.GetQueryRunner(Query query, Int32 queryNumber, Expression expression, Object[] parameters)
at LinqToDB.Linq.QueryRunner.ExecuteQuery[T](Query query, IDataContext dataContext, Mapper`1 mapper, Expression expression, Object[] ps, Int32 queryNumber)+MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at Microsoft.Extensions.Caching.Memory.CacheExtensions.GetOrCreate[TItem](IMemoryCache cache, Object key, Func`2 factory)
at Nop.Core.Caching.MemoryCacheManager.Get[T](CacheKey key, Func`1 acquire) in D:\a\1\s\src\Libraries\Nop.Core\Caching\MemoryCacheManager.cs:line 79
at Nop.Web.Factories.ProductModelFactory.PrepareProductReviewsModel(ProductReviewsModel model, Product product) in D:\a\1\s\src\Presentation\Nop.Web\Factories\ProductModelFactory.cs:line 1441
at Microsoft.Extensions.Caching.Memory.CacheExtensions.GetOrCreate[TItem](IMemoryCache cache, Object key, Func`2 factory)
at Nop.Core.Caching.MemoryCacheManager.Get[T](CacheKey key, Func`1 acquire) in D:\a\1\s\src\Libraries\Nop.Core\Caching\MemoryCacheManager.cs:line 79
at Nop.Plugin.Misc.INKredible.Factories.FactoriesOverridden.ProductModelFactoryOverriden.PrepareProductReviewsModel(ProductReviewsModel model, Product product) in D:\a\1\s\src\Plugins\Nop.Plugin.Misc.INKredible\Factories\FactoriesOverridden\ProductModelFactoryOverriden.cs:line 173
at Nop.Plugin.Misc.INKredible.Factories.MicrodataSnippetsModelFactory.PrepareProductModel(Product product, ProductDetailsModel productDetailsModel) in D:\a\1\s\src\Plugins\Nop.Plugin.Misc.INKredible\Factories\MicrodataSnippetsModelFactory.cs:line 72
at Nop.Plugin.Misc.INKredible.WidgetZoneComponents.MicrodataSnippets.ProductBoxSnippet.Invoke(ViewComponent baseViewComponent, String widgetZone, Object additionalData) in D:\a\1\s\src\Plugins\Nop.Plugin.Misc.INKredible\WidgetZoneComponents\MicrodataSnippets\ProductBoxSnippet.cs:line 39
at Nop.Plugin.Misc.INKredible.Extensions.ViewComponentExtensions.<>c__DisplayClass0_0.<RenderWidgetZoneViewComponentParts>b__1(WidgetZoneViewComponentPart i) in D:\a\1\s\src\Plugins\Nop.Plugin.Misc.INKredible\Extensions\ViewComponentExtensions.cs:line 29
at System.Collections.Generic.List`1.ForEach(Action`1 action)
at Nop.Plugin.Misc.INKredible.Extensions.ViewComponentExtensions.RenderWidgetZoneViewComponentParts(ViewComponent baseViewComponent, String widgetZone, Object additionalData) in D:\a\1\s\src\Plugins\Nop.Plugin.Misc.INKredible\Extensions\ViewComponentExtensions.cs:line 36
The issue looks like to be happening here:
foreach (var q in _reviewTypeService.GetProductReviewReviewTypeMappingsByProductReviewId(pr.Id))
When i started to look into this i've found that IReviewTypeService is registered as singleton in nop 4.30 Nop.Web.Framework.Infrastructure.DependencyRegistrar:
builder.RegisterType<ReviewTypeService>().As<IReviewTypeService>().SingleInstance();
Which may cause the issue, because of db connection in that service is re-used (or attempted to do so) within whole app lifecycle.
The question to developers: What is the purpose of registering IReviewTypeService as singletone or was it done by mistake ?