From ae85cdedd503fa1488947423cdb43db29710c752 Mon Sep 17 00:00:00 2001 From: KharchenkoVV Date: Fri, 21 May 2021 17:42:18 +0500 Subject: [PATCH] =?UTF-8?q?CS2-13:=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=BF=D0=BE=D1=82=D0=BE=D0=BA=D0=BE=D0=B1?= =?UTF-8?q?=D0=B5=D0=B7=D0=BE=D0=BF=D0=B0=D1=81=D0=BD=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D1=8C=20=D0=B4=D0=BB=D1=8F=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D1=85=20=D0=B2=20Ca=D1=81heTable?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/Cache/CacheTable.cs | 382 ++++++++++++------ 1 file changed, 253 insertions(+), 129 deletions(-) diff --git a/AsbCloudInfrastructure/Services/Cache/CacheTable.cs b/AsbCloudInfrastructure/Services/Cache/CacheTable.cs index 0def1e23..7fbe6666 100644 --- a/AsbCloudInfrastructure/Services/Cache/CacheTable.cs +++ b/AsbCloudInfrastructure/Services/Cache/CacheTable.cs @@ -12,6 +12,7 @@ namespace AsbCloudInfrastructure.Services.Cache private readonly DbContext context; private (DateTime refreshDate, IEnumerable entities) data; private readonly List cached; + private readonly ReaderWriterLockSlim cacheLocker = new ReaderWriterLockSlim(); internal CacheTable(DbContext context, (DateTime refreshDate, IEnumerable entities) data) { @@ -24,20 +25,36 @@ namespace AsbCloudInfrastructure.Services.Cache public int Refresh() { - cached.Clear(); - var dbEntities = context.Set().ToList(); - cached.AddRange(dbEntities); - data.refreshDate = DateTime.Now; - return cached.Count; + cacheLocker.EnterWriteLock(); + try + { + cached.Clear(); + var dbEntities = context.Set().ToList(); + cached.AddRange(dbEntities); + data.refreshDate = DateTime.Now; + return cached.Count; + } + finally + { + cacheLocker.ExitWriteLock(); + } } public async Task RefreshAsync(CancellationToken token = default) { - cached.Clear(); - var dbEntities = await context.Set().ToListAsync(token).ConfigureAwait(false); - cached.AddRange(dbEntities); - data.refreshDate = DateTime.Now; - return cached.Count; + cacheLocker.EnterWriteLock(); + try + { + cached.Clear(); + var dbEntities = await context.Set().ToListAsync(token).ConfigureAwait(false); + cached.AddRange(dbEntities); + data.refreshDate = DateTime.Now; + return cached.Count; + } + finally + { + cacheLocker.ExitWriteLock(); + } } private bool CheckRefresh(RefreshMode refreshMode) @@ -184,193 +201,300 @@ namespace AsbCloudInfrastructure.Services.Cache public IEnumerable Update(Func predicate, Action mutation) { - var dbSet = context.Set(); - var dbEntities = dbSet.Where(predicate); - if (dbEntities.Any()) + cacheLocker.EnterWriteLock(); + + try { - foreach (var dbEntity in dbEntities) - mutation(dbEntity); - context.SaveChanges(); + var dbSet = context.Set(); + var dbEntities = dbSet.Where(predicate); + if (dbEntities.Any()) + { + foreach (var dbEntity in dbEntities) + mutation(dbEntity); + context.SaveChanges(); + } + cached.RemoveAll(e => predicate(e)); + cached.AddRange(dbEntities); + return dbEntities; + } + finally + { + cacheLocker.ExitWriteLock(); } - cached.RemoveAll(e => predicate(e)); - cached.AddRange(dbEntities); - return dbEntities; } public async Task> UpdateAsync(Func predicate, Action mutation, CancellationToken token = default) { - var dbSet = context.Set(); - var dbEntities = dbSet.Where(predicate); - if (dbEntities.Any()) + cacheLocker.EnterWriteLock(); + + try { - foreach (var dbEntity in dbEntities) - mutation(dbEntity); - await context.SaveChangesAsync(token).ConfigureAwait(false); + var dbSet = context.Set(); + var dbEntities = dbSet.Where(predicate); + if (dbEntities.Any()) + { + foreach (var dbEntity in dbEntities) + mutation(dbEntity); + await context.SaveChangesAsync(token).ConfigureAwait(false); + } + cached.RemoveAll(e => predicate(e)); + cached.AddRange(dbEntities); + return dbEntities; + } + finally + { + cacheLocker.ExitWriteLock(); } - cached.RemoveAll(e => predicate(e)); - cached.AddRange(dbEntities); - return dbEntities; } public TEntity Upsert(TEntity entity) { - var dbSet = context.Set(); - Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry entityEntry; - if (cached.Contains(entity)) + cacheLocker.EnterWriteLock(); + + try { - entityEntry = dbSet.Update(entity); - cached.Remove(entity); + var dbSet = context.Set(); + Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry entityEntry; + if (cached.Contains(entity)) + { + entityEntry = dbSet.Update(entity); + cached.Remove(entity); + } + else + { + entityEntry = dbSet.Add(entity); + } + + context.SaveChanges(); + + cached.Add(entityEntry.Entity); + + return entityEntry.Entity; } - else + finally { - entityEntry = dbSet.Add(entity); + cacheLocker.ExitWriteLock(); } - - context.SaveChanges(); - - cached.Add(entityEntry.Entity); - - return entityEntry.Entity; } public async Task UpsertAsync(TEntity entity, CancellationToken token = default) { - var dbSet = context.Set(); - Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry entityEntry; + cacheLocker.EnterWriteLock(); - if (cached.Contains(entity)) + try { - entityEntry = dbSet.Update(entity); - cached.Remove(entity); + var dbSet = context.Set(); + Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry entityEntry; + + if (cached.Contains(entity)) + { + entityEntry = dbSet.Update(entity); + cached.Remove(entity); + } + else + { + entityEntry = dbSet.Add(entity); + } + + await context.SaveChangesAsync(token).ConfigureAwait(false); + + cached.Add(entityEntry.Entity); + + return entityEntry.Entity; } - else + finally { - entityEntry = dbSet.Add(entity); + cacheLocker.ExitWriteLock(); } - - await context.SaveChangesAsync(token).ConfigureAwait(false); - - cached.Add(entityEntry.Entity); - - return entityEntry.Entity; } public IEnumerable Upsert(IEnumerable entities) { - var dbSet = context.Set(); + cacheLocker.EnterWriteLock(); - var upsertedEntries = new List>(entities.Count()); - foreach (var entity in entities) + try { - Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry entityEntry; - if (cached.Contains(entity)) + var dbSet = context.Set(); + + var upsertedEntries = new List>(entities.Count()); + foreach (var entity in entities) { - entityEntry = dbSet.Update(entity); - cached.Remove(entity); + Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry entityEntry; + if (cached.Contains(entity)) + { + entityEntry = dbSet.Update(entity); + cached.Remove(entity); + } + else + { + entityEntry = dbSet.Add(entity); + } + upsertedEntries.Add(entityEntry); } - else - { - entityEntry = dbSet.Add(entity); - } - upsertedEntries.Add(entityEntry); + + context.SaveChanges(); + + var upserted = upsertedEntries.Select(e => e.Entity); + + cached.AddRange(upserted); + + return upserted; + } + finally + { + cacheLocker.ExitWriteLock(); } - - context.SaveChanges(); - - var upserted = upsertedEntries.Select(e => e.Entity); - - cached.AddRange(upserted); - - return upserted; } public async Task> UpsertAsync(IEnumerable entities, CancellationToken token = default) { - var dbSet = context.Set(); + cacheLocker.EnterWriteLock(); - var upsertedEntries = new List>(entities.Count()); - foreach (var entity in entities) + try { - Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry entityEntry; - if (cached.Contains(entity)) + var dbSet = context.Set(); + + var upsertedEntries = new List>(entities.Count()); + foreach (var entity in entities) { - entityEntry = dbSet.Update(entity); - cached.Remove(entity); + Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry entityEntry; + if (cached.Contains(entity)) + { + entityEntry = dbSet.Update(entity); + cached.Remove(entity); + } + else + { + entityEntry = dbSet.Add(entity); + } + upsertedEntries.Add(entityEntry); } - else - { - entityEntry = dbSet.Add(entity); - } - upsertedEntries.Add(entityEntry); + + await context.SaveChangesAsync(token).ConfigureAwait(false); + + var upserted = upsertedEntries.Select(e => e.Entity); + + cached.AddRange(upserted); + + return upserted; + } + finally + { + cacheLocker.ExitWriteLock(); } - - await context.SaveChangesAsync(token).ConfigureAwait(false); - - var upserted = upsertedEntries.Select(e => e.Entity); - - cached.AddRange(upserted); - - return upserted; } public void Remove(Func predicate) { - var dbSet = context.Set(); - cached.RemoveAll(e => predicate(e)); - dbSet.RemoveRange(dbSet.Where(predicate)); - context.SaveChanges(); - return; + cacheLocker.EnterWriteLock(); + + try + { + var dbSet = context.Set(); + cached.RemoveAll(e => predicate(e)); + dbSet.RemoveRange(dbSet.Where(predicate)); + context.SaveChanges(); + return; + } + finally + { + cacheLocker.ExitWriteLock(); + } } public async Task RemoveAsync(Func predicate, CancellationToken token = default) { - var dbSet = context.Set(); - cached.RemoveAll(e => predicate(e)); - dbSet.RemoveRange(dbSet.Where(predicate)); - await context.SaveChangesAsync(token).ConfigureAwait(false); - return; + cacheLocker.EnterWriteLock(); + + try + { + var dbSet = context.Set(); + cached.RemoveAll(e => predicate(e)); + dbSet.RemoveRange(dbSet.Where(predicate)); + await context.SaveChangesAsync(token).ConfigureAwait(false); + return; + } + finally + { + cacheLocker.ExitWriteLock(); + } } public TEntity Insert(TEntity entity) { - var dbSet = context.Set(); - var dbEntity = dbSet.Add(entity).Entity; - context.SaveChanges(); - cached.Add(dbEntity); - return dbEntity; + cacheLocker.EnterWriteLock(); + + try + { + var dbSet = context.Set(); + var dbEntity = dbSet.Add(entity).Entity; + context.SaveChanges(); + cached.Add(dbEntity); + return dbEntity; + } + finally + { + cacheLocker.ExitWriteLock(); + } } public async Task InsertAsync(TEntity entity, CancellationToken token = default) { - var dbSet = context.Set(); - var dbEntity = dbSet.Add(entity).Entity; - await context.SaveChangesAsync(token).ConfigureAwait(false); - cached.Add(dbEntity); - return dbEntity; + cacheLocker.EnterWriteLock(); + + try + { + var dbSet = context.Set(); + var dbEntity = dbSet.Add(entity).Entity; + await context.SaveChangesAsync(token).ConfigureAwait(false); + cached.Add(dbEntity); + return dbEntity; + } + finally + { + cacheLocker.ExitWriteLock(); + } } public IEnumerable Insert(IEnumerable newEntities) { - var dbSet = context.Set(); - var dbEntities = new List(newEntities.Count()); - foreach (var item in newEntities) - dbEntities.Add(dbSet.Add(item).Entity); - context.SaveChanges(); - cached.AddRange(dbEntities); - return dbEntities; + cacheLocker.EnterWriteLock(); + + try + { + var dbSet = context.Set(); + var dbEntities = new List(newEntities.Count()); + foreach (var item in newEntities) + dbEntities.Add(dbSet.Add(item).Entity); + context.SaveChanges(); + cached.AddRange(dbEntities); + return dbEntities; + } + finally + { + cacheLocker.ExitWriteLock(); + } } public async Task> InsertAsync(IEnumerable newEntities, CancellationToken token = default) { - var dbSet = context.Set(); - var dbEntities = new List(newEntities.Count()); - foreach (var item in newEntities) - dbEntities.Add(dbSet.Add(item).Entity); - await context.SaveChangesAsync(token).ConfigureAwait(false); - cached.AddRange(dbEntities); - return dbEntities; - } + cacheLocker.EnterWriteLock(); + try + { + var dbSet = context.Set(); + var dbEntities = new List(newEntities.Count()); + foreach (var item in newEntities) + dbEntities.Add(dbSet.Add(item).Entity); + await context.SaveChangesAsync(token).ConfigureAwait(false); + cached.AddRange(dbEntities); + return dbEntities; + } + finally + { + cacheLocker.ExitWriteLock(); + } + } } }