Tengo un proyecto con el núcleo asp.net y el núcleo de la estructura de la entidad, por razones de rendimiento utilizo MemoryCache. La clase ForumQueryManager es para consultar datos del foro y esta clase para datos usa el método CacheManager Get y pasa cachekey y el tiempo de caché de tiempo de espera y un método para cuando el caché está vacío para recuperar datos de la base de datos. Este código funciona casi siempre. pero a veces lanza excepción
Excepción:
Se produjo una excepción no controlada al procesar la solicitud. InvalidOperationException: se inició una segunda operación en este contexto antes de que se completara una operación anterior. No se garantiza que ningún miembro de instancia sea seguro para subprocesos.
Microsoft.EntityFrameworkCore.Internal.ConcurrencyDetector.EnterCriticalSection ()
ForumQueryManager:
public class ForumQueryManager : IForumQueryManager
{
private readonly NashrNegarDbContext _dbContext;
private readonly ICalender _calender;
private readonly ICacheManager _cacheManager;
public ForumQueryManager(NashrNegarDbContext dbContext, ICacheManager cacheManager)
{
_dbContext = dbContext;
_cacheManager = cacheManager;
}
public async Task<List<ForumCategoryDto>> GetAll()
{
var items = await _cacheManager.Get(CacheConstants.ForumCategories, 20, GetForumCategories);
return items;
}
private async Task<List<ForumCategoryDto>> GetForumCategories()
{
var categories = await _dbContext.ForumCategories
.Select(e => new ForumCategoryDto
{
Name = e.Name,
ForumCategoryId = e.ForumCategoryId
}).ToListAsync();
return categories;
}
}
CacheManager:
public class CacheManager: ICacheManager
{
private readonly IMemoryCache _cache;
private readonly CacheSetting _cacheSetting;
public CacheManager(IMemoryCache cache, IOptions<CacheSetting> cacheOption)
{
_cache = cache;
_cacheSetting = cacheOption.Value;
}
public async Task<List<T>> Get<T>(string cacheKey, int expirationMinutes, Func<Task<List<T>>> function)
{
List<T> items;
if (_cacheSetting.MemeoryEnabled)
{
var value = _cache.Get<string>(cacheKey);
if (value == null)
{
items = await function();
value = JsonConvert.SerializeObject(items, Formatting.Indented,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
MissingMemberHandling = MissingMemberHandling.Ignore,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
_cache.Set(cacheKey, value,
new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromMinutes(expirationMinutes)));
}
else
{
items = JsonConvert.DeserializeObject<List<T>>(value);
}
}
else
{
items = await function();
}
return items;
}
}
ForumQueryManager
debe ser transitorio, de lo contrario, la variable _dbContext
se reutilizará.