성능상의 이유로 asp.net 코어 및 엔터티 프레임 워크 코어가있는 프로젝트가 있습니다. 이는 MemoryCache를 사용합니다. ForumQueryManager 클래스는 포럼 데이터와이 클래스를 사용하여 데이터를 쿼리하는 데 사용됩니다. CacheManager 메서드를 가져 와서 캐시 키와 시간 제한 캐시 시간을 전달하고 데이터베이스에서 데이터를 검색하기 위해 캐시가 비어있는 경우 메서드를 전달합니다. 이 코드는 거의 항상 작동합니다. 때로는 예외를이전 작업이 완료되기 전에이 컨텍스트에서 시작된 두 번째 작업
예외를 발생 : 요청을 처리하는 동안
되지 않은 예외가 발생했습니다. InvalidOperationException : 이전 작업이 완료되기 전에이 컨텍스트에서 시작된 두 번째 작업이 입니다. 모든 인스턴스 구성원은 스레드 안전성이 보장 된 이 아닙니다.
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;
}
}
예외는 DbContext가 스레드로부터 안전하지 않다는 것을 분명히 설명합니다. 요청 당 또는 스레드별로 해결하십시오. 어떻게 컨텍스트를'ForumQueryManager'에 넘깁니까? –
DbContext는 요청 당이 코드를 사용합니다. services.AddDbContext (options => options.UseSqlServer (Configuration [ "Data : DefaultConnection : ConnectionString"]))); –
캐시 관리자의 수명은 어떻게됩니까? EF와 일치시킵니다. – ssmith