From 787a6cc7c659ac0304bf494aee8f0d49105b00aa Mon Sep 17 00:00:00 2001 From: Jason Webb Date: Fri, 26 Jul 2024 18:27:20 -0600 Subject: [PATCH] WIP --- Examples/Examples.sln | 22 ++- .../RCommon.RedisCache.csproj | 9 + .../RCommon.DistributedMemoryCache.csproj | 9 + .../Crud/CachingGraphRepository.cs | 176 ++++++++++++++++++ .../Crud/CachingLinqRepository.cs | 135 ++++++++++++++ .../Crud/CachingSqlMapperRepository.cs | 12 ++ .../Crud/ICachingRepository.cs | 13 ++ .../PersistenceCachingOptions.cs | 12 ++ .../RCommon.Persistence.Caching.csproj | 13 ++ 9 files changed, 400 insertions(+), 1 deletion(-) create mode 100644 Examples/RCommon.RedisCache/RCommon.RedisCache.csproj create mode 100644 Src/RCommon.DistributedMemoryCache/RCommon.DistributedMemoryCache.csproj create mode 100644 Src/RCommon.Persistence.Caching/Crud/CachingGraphRepository.cs create mode 100644 Src/RCommon.Persistence.Caching/Crud/CachingLinqRepository.cs create mode 100644 Src/RCommon.Persistence.Caching/Crud/CachingSqlMapperRepository.cs create mode 100644 Src/RCommon.Persistence.Caching/Crud/ICachingRepository.cs create mode 100644 Src/RCommon.Persistence.Caching/PersistenceCachingOptions.cs create mode 100644 Src/RCommon.Persistence.Caching/RCommon.Persistence.Caching.csproj diff --git a/Examples/Examples.sln b/Examples/Examples.sln index 781531d6..bcb92c8a 100644 --- a/Examples/Examples.sln +++ b/Examples/Examples.sln @@ -115,7 +115,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RCommon.FluentValidation", EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Validation", "Validation", "{0F54DCE2-27A5-4D07-B542-6D2A7B50D0EC}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Examples.Validation.FluentValidation", "Validation\Examples.Validation.FluentValidation\Examples.Validation.FluentValidation.csproj", "{256821F9-8160-4819-B0A1-B769C5BBBBB6}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Examples.Validation.FluentValidation", "Validation\Examples.Validation.FluentValidation\Examples.Validation.FluentValidation.csproj", "{256821F9-8160-4819-B0A1-B769C5BBBBB6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RCommon.Persistence.Caching", "..\Src\RCommon.Persistence.Caching\RCommon.Persistence.Caching.csproj", "{B66429EB-4B5F-42F9-9CD7-7334190A14F4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RCommon.DistributedMemoryCache", "..\Src\RCommon.DistributedMemoryCache\RCommon.DistributedMemoryCache.csproj", "{DCF81616-F849-46BF-B7DE-1B30798418D0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RCommon.RedisCache", "RCommon.RedisCache\RCommon.RedisCache.csproj", "{6F9A2678-49D1-4626-B0AF-176B95AF3A72}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -299,6 +305,18 @@ Global {256821F9-8160-4819-B0A1-B769C5BBBBB6}.Debug|Any CPU.Build.0 = Debug|Any CPU {256821F9-8160-4819-B0A1-B769C5BBBBB6}.Release|Any CPU.ActiveCfg = Release|Any CPU {256821F9-8160-4819-B0A1-B769C5BBBBB6}.Release|Any CPU.Build.0 = Release|Any CPU + {B66429EB-4B5F-42F9-9CD7-7334190A14F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B66429EB-4B5F-42F9-9CD7-7334190A14F4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B66429EB-4B5F-42F9-9CD7-7334190A14F4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B66429EB-4B5F-42F9-9CD7-7334190A14F4}.Release|Any CPU.Build.0 = Release|Any CPU + {DCF81616-F849-46BF-B7DE-1B30798418D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DCF81616-F849-46BF-B7DE-1B30798418D0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DCF81616-F849-46BF-B7DE-1B30798418D0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DCF81616-F849-46BF-B7DE-1B30798418D0}.Release|Any CPU.Build.0 = Release|Any CPU + {6F9A2678-49D1-4626-B0AF-176B95AF3A72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6F9A2678-49D1-4626-B0AF-176B95AF3A72}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6F9A2678-49D1-4626-B0AF-176B95AF3A72}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6F9A2678-49D1-4626-B0AF-176B95AF3A72}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -348,6 +366,8 @@ Global {BBBCCC2B-2218-4C32-96EE-C2153A23F643} = {3199F749-0082-41D0-91D3-ECED117F8B08} {0F54DCE2-27A5-4D07-B542-6D2A7B50D0EC} = {3234C3BB-1632-4684-838E-9D6D382D4D4D} {256821F9-8160-4819-B0A1-B769C5BBBBB6} = {0F54DCE2-27A5-4D07-B542-6D2A7B50D0EC} + {DCF81616-F849-46BF-B7DE-1B30798418D0} = {3199F749-0082-41D0-91D3-ECED117F8B08} + {6F9A2678-49D1-4626-B0AF-176B95AF3A72} = {3199F749-0082-41D0-91D3-ECED117F8B08} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {0B0CD26D-8067-4667-863E-6B0EE7EDAA42} diff --git a/Examples/RCommon.RedisCache/RCommon.RedisCache.csproj b/Examples/RCommon.RedisCache/RCommon.RedisCache.csproj new file mode 100644 index 00000000..fa71b7ae --- /dev/null +++ b/Examples/RCommon.RedisCache/RCommon.RedisCache.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/Src/RCommon.DistributedMemoryCache/RCommon.DistributedMemoryCache.csproj b/Src/RCommon.DistributedMemoryCache/RCommon.DistributedMemoryCache.csproj new file mode 100644 index 00000000..fa71b7ae --- /dev/null +++ b/Src/RCommon.DistributedMemoryCache/RCommon.DistributedMemoryCache.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/Src/RCommon.Persistence.Caching/Crud/CachingGraphRepository.cs b/Src/RCommon.Persistence.Caching/Crud/CachingGraphRepository.cs new file mode 100644 index 00000000..5023a0f8 --- /dev/null +++ b/Src/RCommon.Persistence.Caching/Crud/CachingGraphRepository.cs @@ -0,0 +1,176 @@ +using Microsoft.Extensions.Caching.Distributed; +using Microsoft.Extensions.Options; +using RCommon.Collections; +using RCommon.Entities; +using RCommon.Persistence.Crud; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace RCommon.Persistence.Caching.Crud +{ + public class CachingGraphRepository : IGraphRepository + where TEntity : class, IBusinessEntity + { + private readonly IGraphRepository _graphRepository; + private readonly IOptions _cachingConfiguration; + private readonly IDistributedCache _distributedCache; + + public CachingGraphRepository(IGraphRepository graphRepository, IOptions cachingConfiguration, + IDistributedCache distributedCache) + { + _graphRepository = graphRepository; + _cachingConfiguration = cachingConfiguration; + _distributedCache = distributedCache; + } + + public bool Tracking { get => _graphRepository.Tracking; set => _graphRepository.Tracking = value; } + + public Type ElementType => _graphRepository.ElementType; + + public Expression Expression => _graphRepository.Expression; + + public IQueryProvider Provider => _graphRepository.Provider; + + public string DataStoreName { get => _graphRepository.DataStoreName; set => _graphRepository.DataStoreName = value; } + + public async Task AddAsync(TEntity entity, CancellationToken token = default) + { + await _graphRepository.AddAsync(entity, token); + } + + public async Task AnyAsync(Expression> expression, CancellationToken token = default) + { + return await _graphRepository.AnyAsync(expression, token); + } + + public async Task AnyAsync(ISpecification specification, CancellationToken token = default) + { + return await _graphRepository.AnyAsync(specification, token); + } + + public async Task DeleteAsync(TEntity entity, CancellationToken token = default) + { + await _graphRepository.DeleteAsync(entity, token); + } + + public async Task FindAsync(object primaryKey, CancellationToken token = default) + { + return await _graphRepository.FindAsync(primaryKey, token); + } + + public IQueryable FindQuery(ISpecification specification) + { + return _graphRepository.FindQuery(specification); + } + + public IQueryable FindQuery(Expression> expression) + { + return _graphRepository.FindQuery(expression); + } + + public IQueryable FindQuery(Expression> expression, Expression> orderByExpression, bool orderByAscending, int pageNumber = 1, int pageSize = 0) + { + return _graphRepository.FindQuery(expression, orderByExpression, orderByAscending, pageNumber, pageSize); + } + + public IQueryable FindQuery(IPagedSpecification specification) + { + return _graphRepository.FindQuery(specification); + } + + public async Task FindSingleOrDefaultAsync(Expression> expression, CancellationToken token = default) + { + return await _graphRepository.FindSingleOrDefaultAsync(expression, token); + } + + public async Task FindSingleOrDefaultAsync(ISpecification specification, CancellationToken token = default) + { + return await _graphRepository.FindSingleOrDefaultAsync(specification, token); + } + + public async Task GetCountAsync(ISpecification selectSpec, CancellationToken token = default) + { + return await _graphRepository.GetCountAsync(selectSpec, token); + } + + public async Task GetCountAsync(Expression> expression, CancellationToken token = default) + { + return await _graphRepository.GetCountAsync(expression, token); + } + + public IEnumerator GetEnumerator() + { + return _graphRepository.GetEnumerator(); + } + + public IEagerLoadableQueryable Include(Expression> path) + { + return _graphRepository.Include(path); + } + + public IEagerLoadableQueryable ThenInclude(Expression> path) + { + return _graphRepository.ThenInclude(path); + } + + public async Task UpdateAsync(TEntity entity, CancellationToken token = default) + { + await _graphRepository.UpdateAsync(entity, token); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return _graphRepository.GetEnumerator(); + } + + public async Task> FindAsync(Expression> expression, Expression> orderByExpression, bool orderByAscending, int pageNumber = 1, int pageSize = 0, CancellationToken token = default) + { + return await _graphRepository.FindAsync(expression, orderByExpression, orderByAscending, pageNumber, pageSize, token); + } + + public async Task> FindAsync(IPagedSpecification specification, CancellationToken token = default) + { + return await _graphRepository.FindAsync(specification, token); + } + + public async Task> FindAsync(ISpecification specification, CancellationToken token = default) + { + return await _graphRepository.FindAsync(specification, token); + } + + public async Task> FindAsync(Expression> expression, CancellationToken token = default) + { + return await _graphRepository.FindAsync(expression, token); + } + + // Cached items + + public async Task> FindAsync(Expression> expression, Expression> orderByExpression, bool orderByAscending, string cacheKey, int pageNumber = 1, int pageSize = 0, CancellationToken token = default) + { + if (_distributedCache.get) + return await _graphRepository.FindAsync(expression, orderByExpression, orderByAscending, pageNumber, pageSize, token); + } + + public async Task> FindAsync(IPagedSpecification specification, CancellationToken token = default) + { + return await _graphRepository.FindAsync(specification, token); + } + + public async Task> FindAsync(ISpecification specification, CancellationToken token = default) + { + return await _graphRepository.FindAsync(specification, token); + } + + public async Task> FindAsync(Expression> expression, CancellationToken token = default) + { + return await _graphRepository.FindAsync(expression, token); + } + } +} diff --git a/Src/RCommon.Persistence.Caching/Crud/CachingLinqRepository.cs b/Src/RCommon.Persistence.Caching/Crud/CachingLinqRepository.cs new file mode 100644 index 00000000..365ed3a3 --- /dev/null +++ b/Src/RCommon.Persistence.Caching/Crud/CachingLinqRepository.cs @@ -0,0 +1,135 @@ +using RCommon.Collections; +using RCommon.Entities; +using RCommon.Persistence.Crud; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace RCommon.Persistence.Caching.Crud +{ + public class CachingLinqRepository : ILinqRepository + where TEntity : class, IBusinessEntity + { + public Type ElementType => throw new NotImplementedException(); + + public Expression Expression => throw new NotImplementedException(); + + public IQueryProvider Provider => throw new NotImplementedException(); + + public string DataStoreName { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + + public Task AddAsync(TEntity entity, CancellationToken token = default) + { + throw new NotImplementedException(); + } + + public Task AnyAsync(Expression> expression, CancellationToken token = default) + { + throw new NotImplementedException(); + } + + public Task AnyAsync(ISpecification specification, CancellationToken token = default) + { + throw new NotImplementedException(); + } + + public Task DeleteAsync(TEntity entity, CancellationToken token = default) + { + throw new NotImplementedException(); + } + + public Task> FindAsync(Expression> expression, Expression> orderByExpression, bool orderByAscending, int pageNumber = 1, int pageSize = 0, CancellationToken token = default) + { + throw new NotImplementedException(); + } + + public Task> FindAsync(IPagedSpecification specification, CancellationToken token = default) + { + throw new NotImplementedException(); + } + + public Task> FindAsync(ISpecification specification, CancellationToken token = default) + { + throw new NotImplementedException(); + } + + public Task> FindAsync(Expression> expression, CancellationToken token = default) + { + throw new NotImplementedException(); + } + + public Task FindAsync(object primaryKey, CancellationToken token = default) + { + throw new NotImplementedException(); + } + + public IQueryable FindQuery(ISpecification specification) + { + throw new NotImplementedException(); + } + + public IQueryable FindQuery(Expression> expression) + { + throw new NotImplementedException(); + } + + public IQueryable FindQuery(Expression> expression, Expression> orderByExpression, bool orderByAscending, int pageNumber = 1, int pageSize = 0) + { + throw new NotImplementedException(); + } + + public IQueryable FindQuery(IPagedSpecification specification) + { + throw new NotImplementedException(); + } + + public Task FindSingleOrDefaultAsync(Expression> expression, CancellationToken token = default) + { + throw new NotImplementedException(); + } + + public Task FindSingleOrDefaultAsync(ISpecification specification, CancellationToken token = default) + { + throw new NotImplementedException(); + } + + public Task GetCountAsync(ISpecification selectSpec, CancellationToken token = default) + { + throw new NotImplementedException(); + } + + public Task GetCountAsync(Expression> expression, CancellationToken token = default) + { + throw new NotImplementedException(); + } + + public IEnumerator GetEnumerator() + { + throw new NotImplementedException(); + } + + public IEagerLoadableQueryable Include(Expression> path) + { + throw new NotImplementedException(); + } + + public IEagerLoadableQueryable ThenInclude(Expression> path) + { + throw new NotImplementedException(); + } + + public Task UpdateAsync(TEntity entity, CancellationToken token = default) + { + throw new NotImplementedException(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + } +} diff --git a/Src/RCommon.Persistence.Caching/Crud/CachingSqlMapperRepository.cs b/Src/RCommon.Persistence.Caching/Crud/CachingSqlMapperRepository.cs new file mode 100644 index 00000000..d21ce93a --- /dev/null +++ b/Src/RCommon.Persistence.Caching/Crud/CachingSqlMapperRepository.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RCommon.Persistence.Caching.Crud +{ + public class CachingSqlMapperRepository + { + } +} diff --git a/Src/RCommon.Persistence.Caching/Crud/ICachingRepository.cs b/Src/RCommon.Persistence.Caching/Crud/ICachingRepository.cs new file mode 100644 index 00000000..bd899375 --- /dev/null +++ b/Src/RCommon.Persistence.Caching/Crud/ICachingRepository.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RCommon.Persistence.Caching.Crud +{ + public interface ICachingRepository + { + + } +} diff --git a/Src/RCommon.Persistence.Caching/PersistenceCachingOptions.cs b/Src/RCommon.Persistence.Caching/PersistenceCachingOptions.cs new file mode 100644 index 00000000..15c51501 --- /dev/null +++ b/Src/RCommon.Persistence.Caching/PersistenceCachingOptions.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RCommon.Persistence.Caching +{ + public class PersistenceCachingOptions + { + } +} diff --git a/Src/RCommon.Persistence.Caching/RCommon.Persistence.Caching.csproj b/Src/RCommon.Persistence.Caching/RCommon.Persistence.Caching.csproj new file mode 100644 index 00000000..8c7b2f91 --- /dev/null +++ b/Src/RCommon.Persistence.Caching/RCommon.Persistence.Caching.csproj @@ -0,0 +1,13 @@ + + + + net8.0 + enable + enable + + + + + + +