CS2-13: Добавлена потокобезопасность для данных в CaсheTable

This commit is contained in:
KharchenkoVV 2021-05-21 17:42:18 +05:00
parent 7b00cedb47
commit ae85cdedd5

View File

@ -12,6 +12,7 @@ namespace AsbCloudInfrastructure.Services.Cache
private readonly DbContext context; private readonly DbContext context;
private (DateTime refreshDate, IEnumerable<object> entities) data; private (DateTime refreshDate, IEnumerable<object> entities) data;
private readonly List<TEntity> cached; private readonly List<TEntity> cached;
private readonly ReaderWriterLockSlim cacheLocker = new ReaderWriterLockSlim();
internal CacheTable(DbContext context, (DateTime refreshDate, IEnumerable<object> entities) data) internal CacheTable(DbContext context, (DateTime refreshDate, IEnumerable<object> entities) data)
{ {
@ -23,6 +24,9 @@ namespace AsbCloudInfrastructure.Services.Cache
public TEntity this[int index] { get => cached.ElementAt(index); } public TEntity this[int index] { get => cached.ElementAt(index); }
public int Refresh() public int Refresh()
{
cacheLocker.EnterWriteLock();
try
{ {
cached.Clear(); cached.Clear();
var dbEntities = context.Set<TEntity>().ToList(); var dbEntities = context.Set<TEntity>().ToList();
@ -30,8 +34,16 @@ namespace AsbCloudInfrastructure.Services.Cache
data.refreshDate = DateTime.Now; data.refreshDate = DateTime.Now;
return cached.Count; return cached.Count;
} }
finally
{
cacheLocker.ExitWriteLock();
}
}
public async Task<int> RefreshAsync(CancellationToken token = default) public async Task<int> RefreshAsync(CancellationToken token = default)
{
cacheLocker.EnterWriteLock();
try
{ {
cached.Clear(); cached.Clear();
var dbEntities = await context.Set<TEntity>().ToListAsync(token).ConfigureAwait(false); var dbEntities = await context.Set<TEntity>().ToListAsync(token).ConfigureAwait(false);
@ -39,6 +51,11 @@ namespace AsbCloudInfrastructure.Services.Cache
data.refreshDate = DateTime.Now; data.refreshDate = DateTime.Now;
return cached.Count; return cached.Count;
} }
finally
{
cacheLocker.ExitWriteLock();
}
}
private bool CheckRefresh(RefreshMode refreshMode) private bool CheckRefresh(RefreshMode refreshMode)
{ {
@ -183,6 +200,10 @@ namespace AsbCloudInfrastructure.Services.Cache
} }
public IEnumerable<TEntity> Update(Func<TEntity, bool> predicate, Action<TEntity> mutation) public IEnumerable<TEntity> Update(Func<TEntity, bool> predicate, Action<TEntity> mutation)
{
cacheLocker.EnterWriteLock();
try
{ {
var dbSet = context.Set<TEntity>(); var dbSet = context.Set<TEntity>();
var dbEntities = dbSet.Where(predicate); var dbEntities = dbSet.Where(predicate);
@ -196,8 +217,17 @@ namespace AsbCloudInfrastructure.Services.Cache
cached.AddRange(dbEntities); cached.AddRange(dbEntities);
return dbEntities; return dbEntities;
} }
finally
{
cacheLocker.ExitWriteLock();
}
}
public async Task<IEnumerable<TEntity>> UpdateAsync(Func<TEntity, bool> predicate, Action<TEntity> mutation, CancellationToken token = default) public async Task<IEnumerable<TEntity>> UpdateAsync(Func<TEntity, bool> predicate, Action<TEntity> mutation, CancellationToken token = default)
{
cacheLocker.EnterWriteLock();
try
{ {
var dbSet = context.Set<TEntity>(); var dbSet = context.Set<TEntity>();
var dbEntities = dbSet.Where(predicate); var dbEntities = dbSet.Where(predicate);
@ -211,8 +241,17 @@ namespace AsbCloudInfrastructure.Services.Cache
cached.AddRange(dbEntities); cached.AddRange(dbEntities);
return dbEntities; return dbEntities;
} }
finally
{
cacheLocker.ExitWriteLock();
}
}
public TEntity Upsert(TEntity entity) public TEntity Upsert(TEntity entity)
{
cacheLocker.EnterWriteLock();
try
{ {
var dbSet = context.Set<TEntity>(); var dbSet = context.Set<TEntity>();
Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry<TEntity> entityEntry; Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry<TEntity> entityEntry;
@ -232,10 +271,19 @@ namespace AsbCloudInfrastructure.Services.Cache
return entityEntry.Entity; return entityEntry.Entity;
} }
finally
{
cacheLocker.ExitWriteLock();
}
}
public async Task<TEntity> UpsertAsync(TEntity entity, CancellationToken token = default) public async Task<TEntity> UpsertAsync(TEntity entity, CancellationToken token = default)
{
cacheLocker.EnterWriteLock();
try
{ {
var dbSet = context.Set<TEntity>(); var dbSet = context.Set<TEntity>();
Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry<TEntity> entityEntry; Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry<TEntity> entityEntry;
@ -256,8 +304,17 @@ namespace AsbCloudInfrastructure.Services.Cache
return entityEntry.Entity; return entityEntry.Entity;
} }
finally
{
cacheLocker.ExitWriteLock();
}
}
public IEnumerable<TEntity> Upsert(IEnumerable<TEntity> entities) public IEnumerable<TEntity> Upsert(IEnumerable<TEntity> entities)
{
cacheLocker.EnterWriteLock();
try
{ {
var dbSet = context.Set<TEntity>(); var dbSet = context.Set<TEntity>();
@ -285,8 +342,17 @@ namespace AsbCloudInfrastructure.Services.Cache
return upserted; return upserted;
} }
finally
{
cacheLocker.ExitWriteLock();
}
}
public async Task<IEnumerable<TEntity>> UpsertAsync(IEnumerable<TEntity> entities, CancellationToken token = default) public async Task<IEnumerable<TEntity>> UpsertAsync(IEnumerable<TEntity> entities, CancellationToken token = default)
{
cacheLocker.EnterWriteLock();
try
{ {
var dbSet = context.Set<TEntity>(); var dbSet = context.Set<TEntity>();
@ -314,7 +380,16 @@ namespace AsbCloudInfrastructure.Services.Cache
return upserted; return upserted;
} }
finally
{
cacheLocker.ExitWriteLock();
}
}
public void Remove(Func<TEntity, bool> predicate) public void Remove(Func<TEntity, bool> predicate)
{
cacheLocker.EnterWriteLock();
try
{ {
var dbSet = context.Set<TEntity>(); var dbSet = context.Set<TEntity>();
cached.RemoveAll(e => predicate(e)); cached.RemoveAll(e => predicate(e));
@ -322,8 +397,17 @@ namespace AsbCloudInfrastructure.Services.Cache
context.SaveChanges(); context.SaveChanges();
return; return;
} }
finally
{
cacheLocker.ExitWriteLock();
}
}
public async Task RemoveAsync(Func<TEntity, bool> predicate, CancellationToken token = default) public async Task RemoveAsync(Func<TEntity, bool> predicate, CancellationToken token = default)
{
cacheLocker.EnterWriteLock();
try
{ {
var dbSet = context.Set<TEntity>(); var dbSet = context.Set<TEntity>();
cached.RemoveAll(e => predicate(e)); cached.RemoveAll(e => predicate(e));
@ -331,8 +415,17 @@ namespace AsbCloudInfrastructure.Services.Cache
await context.SaveChangesAsync(token).ConfigureAwait(false); await context.SaveChangesAsync(token).ConfigureAwait(false);
return; return;
} }
finally
{
cacheLocker.ExitWriteLock();
}
}
public TEntity Insert(TEntity entity) public TEntity Insert(TEntity entity)
{
cacheLocker.EnterWriteLock();
try
{ {
var dbSet = context.Set<TEntity>(); var dbSet = context.Set<TEntity>();
var dbEntity = dbSet.Add(entity).Entity; var dbEntity = dbSet.Add(entity).Entity;
@ -340,8 +433,17 @@ namespace AsbCloudInfrastructure.Services.Cache
cached.Add(dbEntity); cached.Add(dbEntity);
return dbEntity; return dbEntity;
} }
finally
{
cacheLocker.ExitWriteLock();
}
}
public async Task<TEntity> InsertAsync(TEntity entity, CancellationToken token = default) public async Task<TEntity> InsertAsync(TEntity entity, CancellationToken token = default)
{
cacheLocker.EnterWriteLock();
try
{ {
var dbSet = context.Set<TEntity>(); var dbSet = context.Set<TEntity>();
var dbEntity = dbSet.Add(entity).Entity; var dbEntity = dbSet.Add(entity).Entity;
@ -349,8 +451,17 @@ namespace AsbCloudInfrastructure.Services.Cache
cached.Add(dbEntity); cached.Add(dbEntity);
return dbEntity; return dbEntity;
} }
finally
{
cacheLocker.ExitWriteLock();
}
}
public IEnumerable<TEntity> Insert(IEnumerable<TEntity> newEntities) public IEnumerable<TEntity> Insert(IEnumerable<TEntity> newEntities)
{
cacheLocker.EnterWriteLock();
try
{ {
var dbSet = context.Set<TEntity>(); var dbSet = context.Set<TEntity>();
var dbEntities = new List<TEntity>(newEntities.Count()); var dbEntities = new List<TEntity>(newEntities.Count());
@ -360,8 +471,17 @@ namespace AsbCloudInfrastructure.Services.Cache
cached.AddRange(dbEntities); cached.AddRange(dbEntities);
return dbEntities; return dbEntities;
} }
finally
{
cacheLocker.ExitWriteLock();
}
}
public async Task<IEnumerable<TEntity>> InsertAsync(IEnumerable<TEntity> newEntities, CancellationToken token = default) public async Task<IEnumerable<TEntity>> InsertAsync(IEnumerable<TEntity> newEntities, CancellationToken token = default)
{
cacheLocker.EnterWriteLock();
try
{ {
var dbSet = context.Set<TEntity>(); var dbSet = context.Set<TEntity>();
var dbEntities = new List<TEntity>(newEntities.Count()); var dbEntities = new List<TEntity>(newEntities.Count());
@ -371,6 +491,10 @@ namespace AsbCloudInfrastructure.Services.Cache
cached.AddRange(dbEntities); cached.AddRange(dbEntities);
return dbEntities; return dbEntities;
} }
finally
{
cacheLocker.ExitWriteLock();
}
}
} }
} }