Skip to content

Instantly share code, notes, and snippets.

@danielDevelops
Last active November 27, 2019 17:59
Show Gist options
  • Save danielDevelops/cccd672de9f3b95a4d62b359a5dbd4f6 to your computer and use it in GitHub Desktop.
Save danielDevelops/cccd672de9f3b95a4d62b359a5dbd4f6 to your computer and use it in GitHub Desktop.
.Net Caching Engine
using CommonInterfaces.Infrastructure;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Cache
{
public class CacheContainer : ICacheContainer
{
readonly ConcurrentDictionary<string, IData<dynamic>> _cache = new ConcurrentDictionary<string, IData<dynamic>>();
public void AddItemToCache<T>(string cacheName,
T data,
Func<ICustomContext, Task<T>> reloadMethodAsync,
bool forceImmediateReload = false,
int timeoutInMinutes = 10) where T : class
{
if (timeoutInMinutes < 1)
throw new InvalidOperationException("You cannot set a cache timeout of less than one minute!!!!");
Func<ICustomContext, Task<dynamic>> reload = async (ICustomContext ctx) => await reloadMethodAsync(ctx);
IData<dynamic> cacheItem = new Data<dynamic>(data, reload, new TimeSpan(0, timeoutInMinutes, 0));
_cache.TryAdd(cacheName,cacheItem);
}
public async Task<T> GetItemFromCache<T>(ICustomContext context,
string cacheName,
bool forceImmediateReload = false) where T : class
{
if (!_cache.TryGetValue(cacheName, out IData<dynamic> cachedDataObject))
return null;
var value = await cachedDataObject.GetAsync(context, forceImmediateReload);
return value;
}
public async Task<T> GetAndLoadCacheItemAsync<T>(ICustomContext context,
string cacheName,
Func<ICustomContext, Task<T>> reloadMethodAsync,
bool forceImmediateReload = false,
int timeoutInMinutes = 10) where T : class
{
if (_cache.TryGetValue(cacheName, out IData<dynamic> cachedDataObject))
{
return await cachedDataObject.GetAsync(context, forceImmediateReload);
}
var data = await reloadMethodAsync(context);
AddItemToCache(cacheName, data, reloadMethodAsync, forceImmediateReload, timeoutInMinutes);
return data;
}
public async Task ReloadCacheAsync(ICustomContext context)
{
foreach (var item in _cache)
{
await item.Value.ReloadDataAsync(context);
}
}
}
}
using CommonInterfaces.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Cache
{
internal class Data<T> : IData<T> where T : class
{
readonly Func<ICustomContext, Task<T>> _reloadMethodAsync;
readonly TimeSpan _cacheTimeout;
T _cachedData = null;
public Data(T data, Func<ICustomContext, Task<T>> reloadMethodAsync, TimeSpan cacheTimeout)
{
_cachedData = data;
_cacheTimeout = cacheTimeout;
_reloadMethodAsync = reloadMethodAsync;
}
public DateTime Updated { get; private set; } = DateTime.Now;
public bool IsExpired => Updated.Add(_cacheTimeout) < DateTime.Now;
public async Task ReloadDataAsync(ICustomContext context)
{
_cachedData = await _reloadMethodAsync(context );
Updated = DateTime.Now;
}
public async Task<T> GetAsync(ICustomContext context, bool forceReload = false)
{
if (IsExpired || forceReload)
await ReloadDataAsync(context);
return _cachedData;
}
}
}
using CommonInterfaces.Infrastructure;
using System;
using System.Threading.Tasks;
namespace Cache
{
public interface ICacheContainer
{
void AddItemToCache<T>(string cacheName,
T data,
Func<ICustomContext, Task<T>> reloadMethodAsync,
bool forceImmediateReload,
int timeoutInMinutes = 10) where T : class;
Task<T> GetAndLoadCacheItemAsync<T>(ICustomContext context,
string cacheName,
Func<ICustomContext, Task<T>> reloadMethodAsync,
bool forceImmediateReload = false,
int timeoutInMinutes = 10) where T : class;
Task<T> GetItemFromCache<T>(ICustomContext context,
string cacheName,
bool forceImmediateReload = false) where T : class;
Task ReloadCacheAsync(ICustomContext context);
}
}
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Metadata;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore.Infrastructure;
using System.Threading;
namespace CommonInterfaces.Infrastructure
{
public interface ICustomContext : IDisposable
{
DbSet<TEntity> Set<TEntity>() where TEntity : class;
IModel Model { get; }
ChangeTracker ChangeTracker { get; }
EntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity : class;
DatabaseFacade Database { get; }
Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default);
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
Task BulkInsertAsync<TEntity>(IList<TEntity> entities) where TEntity : class;
bool IsDisposed { get; }
}
}
using CommonInterfaces.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Cache
{
public interface IData<T>
{
Task<T> GetAsync(ICustomContext context, bool forceReload = false);
Task ReloadDataAsync(ICustomContext context);
DateTime Updated { get; }
bool IsExpired { get; }
}
}
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace CommonInterfaces.Infrastructure
{
public interface IGenericRepository<T> where T: class, new()
{
T Insert(T entity, string createdBy);
Task<IEnumerable<T>> BulkInsertAsync(IEnumerable<T> entites, string createdBy);
Task<T> GetByIDAsync(object id);
Task<IEnumerable<T>> GetAsync(
Expression<Func<T, bool>> filter = null,
IEnumerable<Expression<Func<T, object>>> includeProperties = null,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null,
int skip = 0,
int? take = default(int?),
bool disableCacheForQueryPlan = false);
IQueryable<T> GetQueryable(
Expression<Func<T, bool>> filter = null,
IEnumerable<Expression<Func<T, object>>> includeProperties = null,
bool disableCacheForQueryPlan = false);
void Update(T entity, string modifiedBy, params Expression<Func<T, object>>[] changedProperties);
void Delete(T entityToDelete);
void Delete(object id);
Task ExecuteStoredProcedureAsync(string sql, int timeoutInSeconds = 30, params object[] parameters);
Task<IEnumerable<TT>> ExecuteStoredProcedureAsync<TT>(string sql, int timeoutInSeconds = 30, params SqlParameter[] parameters) where TT : class, new();
Task<IEnumerable<TT>> ExecuteDynamicStoredProcedureAsync<TT>(string sprocName, int timeoutInSeconds = 30, params object[] parameterObjects) where TT : class, new();
Task ExecuteSQLAsync(string sql, int timeoutInSeconds = 30);
Task TruncateAsync();
void Save();
Task SaveAsync();
T CreateDetachedEntity(T entity);
void Detach(T entity);
void Attach(T entity);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment