Moves repository caching logic into new CachePolicies.
This commit is contained in:
222
src/Umbraco.Core/Cache/DefaultRepositoryCachePolicy.cs
Normal file
222
src/Umbraco.Core/Cache/DefaultRepositoryCachePolicy.cs
Normal file
@@ -0,0 +1,222 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// The default cache policy for retrieving a single entity
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
/// <typeparam name="TId"></typeparam>
|
||||
internal class DefaultRepositoryCachePolicy<TEntity, TId> : DisposableObject, IRepositoryCachePolicy<TEntity, TId>
|
||||
where TEntity : class, IAggregateRoot
|
||||
{
|
||||
private readonly RepositoryCachePolicyOptions _options;
|
||||
protected IRuntimeCacheProvider Cache { get; private set; }
|
||||
private Action _action;
|
||||
|
||||
public DefaultRepositoryCachePolicy(IRuntimeCacheProvider cache, RepositoryCachePolicyOptions options)
|
||||
{
|
||||
_options = options;
|
||||
Cache = cache;
|
||||
}
|
||||
|
||||
public string GetCacheIdKey(object id)
|
||||
{
|
||||
return string.Format("{0}{1}", GetCacheTypeKey(), id);
|
||||
}
|
||||
|
||||
public string GetCacheTypeKey()
|
||||
{
|
||||
return string.Format("uRepo_{0}_", typeof(TEntity).Name);
|
||||
}
|
||||
|
||||
public void CreateOrUpdate(TEntity entity, Action<TEntity> persistMethod)
|
||||
{
|
||||
var cacheKey = GetCacheIdKey(entity.Id);
|
||||
|
||||
try
|
||||
{
|
||||
persistMethod(entity);
|
||||
|
||||
//set the disposal action
|
||||
SetCacheAction(() => Cache.InsertCacheItem(cacheKey, () => entity));
|
||||
|
||||
////If there's a GetAll zero count cache, ensure it is cleared
|
||||
//_cache.ClearCacheItem(GetCacheTypeKey());
|
||||
}
|
||||
catch
|
||||
{
|
||||
//if an exception is thrown we need to remove the entry from cache, this is ONLY a work around because of the way
|
||||
// that we cache entities: http://issues.umbraco.org/issue/U4-4259
|
||||
Cache.ClearCacheItem(cacheKey);
|
||||
|
||||
////If there's a GetAll zero count cache, ensure it is cleared
|
||||
//_cache.ClearCacheItem(GetCacheTypeKey());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove(TEntity entity, Action<TEntity> persistMethod)
|
||||
{
|
||||
persistMethod(entity);
|
||||
|
||||
//set the disposal action
|
||||
var cacheKey = GetCacheIdKey(entity.Id);
|
||||
SetCacheAction(() => Cache.ClearCacheItem(cacheKey));
|
||||
|
||||
////If there's a GetAll zero count cache, ensure it is cleared
|
||||
//_cache.ClearCacheItem(GetCacheTypeKey());
|
||||
}
|
||||
|
||||
public TEntity Get(TId id, Func<TId, TEntity> getFromRepo)
|
||||
{
|
||||
var cacheKey = GetCacheIdKey(id);
|
||||
var fromCache = Cache.GetCacheItem<TEntity>(cacheKey);
|
||||
if (fromCache != null)
|
||||
return fromCache;
|
||||
|
||||
var entity = getFromRepo(id);
|
||||
|
||||
//set the disposal action
|
||||
SetCacheAction(cacheKey, entity);
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
public TEntity Get(TId id)
|
||||
{
|
||||
var cacheKey = GetCacheIdKey(id);
|
||||
return Cache.GetCacheItem<TEntity>(cacheKey);
|
||||
}
|
||||
|
||||
public bool Exists(TId id, Func<TId, bool> getFromRepo)
|
||||
{
|
||||
var cacheKey = GetCacheIdKey(id);
|
||||
var fromCache = Cache.GetCacheItem<TEntity>(cacheKey);
|
||||
return fromCache != null || getFromRepo(id);
|
||||
}
|
||||
|
||||
public virtual TEntity[] GetAll(TId[] ids, Func<TId[], IEnumerable<TEntity>> getFromRepo)
|
||||
{
|
||||
if (ids.Any())
|
||||
{
|
||||
var entities = ids.Select(Get).ToArray();
|
||||
if (ids.Length.Equals(entities.Length) && entities.Any(x => x == null) == false)
|
||||
return entities;
|
||||
}
|
||||
else
|
||||
{
|
||||
var allEntities = GetAllFromCache();
|
||||
if (allEntities.Any())
|
||||
{
|
||||
if (_options.GetAllCacheValidateCount)
|
||||
{
|
||||
//Get count of all entities of current type (TEntity) to ensure cached result is correct
|
||||
var totalCount = _options.PerformCount();
|
||||
if (allEntities.Length == totalCount)
|
||||
return allEntities;
|
||||
}
|
||||
else
|
||||
{
|
||||
return allEntities;
|
||||
}
|
||||
}
|
||||
else if (_options.GetAllCacheAllowZeroCount)
|
||||
{
|
||||
//if the repository allows caching a zero count, then check the zero count cache
|
||||
var zeroCount = Cache.GetCacheItem<TEntity[]>(GetCacheTypeKey());
|
||||
if (zeroCount != null && zeroCount.Any() == false)
|
||||
{
|
||||
//there is a zero count cache so return an empty list
|
||||
return new TEntity[] {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//we need to do the lookup from the repo
|
||||
var entityCollection = getFromRepo(ids)
|
||||
//ensure we don't include any null refs in the returned collection!
|
||||
.WhereNotNull()
|
||||
.ToArray();
|
||||
|
||||
//set the disposal action
|
||||
SetCacheAction(ids, entityCollection);
|
||||
|
||||
return entityCollection;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs the lookup for all entities of this type from the cache
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected virtual TEntity[] GetAllFromCache()
|
||||
{
|
||||
var allEntities = Cache.GetCacheItemsByKeySearch<TEntity>(GetCacheTypeKey())
|
||||
.WhereNotNull()
|
||||
.ToArray();
|
||||
return allEntities.Any() ? allEntities : new TEntity[] {};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The disposal performs the caching
|
||||
/// </summary>
|
||||
protected override void DisposeResources()
|
||||
{
|
||||
if (_action != null)
|
||||
{
|
||||
_action();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the action to execute on disposal for a single entity
|
||||
/// </summary>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <param name="entity"></param>
|
||||
protected virtual void SetCacheAction(string cacheKey, TEntity entity)
|
||||
{
|
||||
SetCacheAction(() => Cache.InsertCacheItem(cacheKey, () => entity));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the action to execute on disposal for an entity collection
|
||||
/// </summary>
|
||||
/// <param name="ids"></param>
|
||||
/// <param name="entityCollection"></param>
|
||||
protected virtual void SetCacheAction(TId[] ids, TEntity[] entityCollection)
|
||||
{
|
||||
SetCacheAction(() =>
|
||||
{
|
||||
//This option cannot execute if we are looking up specific Ids
|
||||
if (ids.Any() == false && entityCollection.Length == 0 && _options.GetAllCacheAllowZeroCount)
|
||||
{
|
||||
//there was nothing returned but we want to cache a zero count result so add an TEntity[] to the cache
|
||||
// to signify that there is a zero count cache
|
||||
Cache.InsertCacheItem(GetCacheTypeKey(), () => new TEntity[] {});
|
||||
}
|
||||
else
|
||||
{
|
||||
//This is the default behavior, we'll individually cache each item so that if/when these items are resolved
|
||||
// by id, they are returned from the already existing cache.
|
||||
foreach (var entity in entityCollection.WhereNotNull())
|
||||
{
|
||||
var localCopy = entity;
|
||||
Cache.InsertCacheItem(GetCacheIdKey(entity.Id), () => localCopy);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the action to execute on disposal
|
||||
/// </summary>
|
||||
/// <param name="action"></param>
|
||||
protected void SetCacheAction(Action action)
|
||||
{
|
||||
_action = action;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates cache policies
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
/// <typeparam name="TId"></typeparam>
|
||||
internal class DefaultRepositoryCachePolicyFactory<TEntity, TId> : IRepositoryCachePolicyFactory<TEntity, TId>
|
||||
where TEntity : class, IAggregateRoot
|
||||
{
|
||||
private readonly IRuntimeCacheProvider _runtimeCache;
|
||||
private readonly RepositoryCachePolicyOptions _options;
|
||||
|
||||
public DefaultRepositoryCachePolicyFactory(IRuntimeCacheProvider runtimeCache, RepositoryCachePolicyOptions options)
|
||||
{
|
||||
_runtimeCache = runtimeCache;
|
||||
_options = options;
|
||||
}
|
||||
|
||||
public virtual IRepositoryCachePolicy<TEntity, TId> CreatePolicy()
|
||||
{
|
||||
return new DefaultRepositoryCachePolicy<TEntity, TId>(_runtimeCache, _options);
|
||||
}
|
||||
}
|
||||
}
|
||||
57
src/Umbraco.Core/Cache/FullDataSetRepositoryCachePolicy.cs
Normal file
57
src/Umbraco.Core/Cache/FullDataSetRepositoryCachePolicy.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Collections;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// A caching policy that caches an entire dataset as a single collection
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
/// <typeparam name="TId"></typeparam>
|
||||
internal class FullDataSetRepositoryCachePolicy<TEntity, TId> : DefaultRepositoryCachePolicy<TEntity, TId>
|
||||
where TEntity : class, IAggregateRoot
|
||||
{
|
||||
public FullDataSetRepositoryCachePolicy(IRuntimeCacheProvider cache) : base(cache, new RepositoryCachePolicyOptions())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For this type of caching policy, we don't cache individual items
|
||||
/// </summary>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <param name="entity"></param>
|
||||
protected override void SetCacheAction(string cacheKey, TEntity entity)
|
||||
{
|
||||
//do nothing
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the action to execute on disposal for an entity collection
|
||||
/// </summary>
|
||||
/// <param name="ids"></param>
|
||||
/// <param name="entityCollection"></param>
|
||||
protected override void SetCacheAction(TId[] ids, TEntity[] entityCollection)
|
||||
{
|
||||
//for this type of caching policy, we don't want to cache any GetAll request containing specific Ids
|
||||
if (ids.Any()) return;
|
||||
|
||||
//set the disposal action
|
||||
SetCacheAction(() =>
|
||||
{
|
||||
//We want to cache the result as a single collection
|
||||
Cache.InsertCacheItem(GetCacheTypeKey(), () => new DeepCloneableList<TEntity>(entityCollection));
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This policy will cache the full data set as a single collection
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected override TEntity[] GetAllFromCache()
|
||||
{
|
||||
var found = Cache.GetCacheItem<DeepCloneableList<TEntity>>(GetCacheTypeKey());
|
||||
return found == null ? new TEntity[] { } : found.WhereNotNull().ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates cache policies
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
/// <typeparam name="TId"></typeparam>
|
||||
internal class FullDataSetRepositoryCachePolicyFactory<TEntity, TId> : IRepositoryCachePolicyFactory<TEntity, TId>
|
||||
where TEntity : class, IAggregateRoot
|
||||
{
|
||||
private readonly IRuntimeCacheProvider _runtimeCache;
|
||||
|
||||
public FullDataSetRepositoryCachePolicyFactory(IRuntimeCacheProvider runtimeCache)
|
||||
{
|
||||
_runtimeCache = runtimeCache;
|
||||
}
|
||||
|
||||
public virtual IRepositoryCachePolicy<TEntity, TId> CreatePolicy()
|
||||
{
|
||||
return new FullDataSetRepositoryCachePolicy<TEntity, TId>(_runtimeCache);
|
||||
}
|
||||
}
|
||||
}
|
||||
20
src/Umbraco.Core/Cache/IRepositoryCachePolicy.cs
Normal file
20
src/Umbraco.Core/Cache/IRepositoryCachePolicy.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
internal interface IRepositoryCachePolicy<TEntity, TId> : IDisposable
|
||||
where TEntity : class, IAggregateRoot
|
||||
{
|
||||
TEntity Get(TId id, Func<TId, TEntity> getFromRepo);
|
||||
TEntity Get(TId id);
|
||||
bool Exists(TId id, Func<TId, bool> getFromRepo);
|
||||
|
||||
string GetCacheIdKey(object id);
|
||||
string GetCacheTypeKey();
|
||||
void CreateOrUpdate(TEntity entity, Action<TEntity> persistMethod);
|
||||
void Remove(TEntity entity, Action<TEntity> persistMethod);
|
||||
TEntity[] GetAll(TId[] ids, Func<TId[], IEnumerable<TEntity>> getFromRepo);
|
||||
}
|
||||
}
|
||||
9
src/Umbraco.Core/Cache/IRepositoryCachePolicyFactory.cs
Normal file
9
src/Umbraco.Core/Cache/IRepositoryCachePolicyFactory.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
internal interface IRepositoryCachePolicyFactory<TEntity, TId> where TEntity : class, IAggregateRoot
|
||||
{
|
||||
IRepositoryCachePolicy<TEntity, TId> CreatePolicy();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Collections;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// A caching policy that ignores all caches for GetAll - it will only cache calls for individual items
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
/// <typeparam name="TId"></typeparam>
|
||||
internal class OnlySingleItemsRepositoryCachePolicy<TEntity, TId> : DefaultRepositoryCachePolicy<TEntity, TId>
|
||||
where TEntity : class, IAggregateRoot
|
||||
{
|
||||
public OnlySingleItemsRepositoryCachePolicy(IRuntimeCacheProvider cache, RepositoryCachePolicyOptions options) : base(cache, options)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void SetCacheAction(TId[] ids, TEntity[] entityCollection)
|
||||
{
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates cache policies
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
/// <typeparam name="TId"></typeparam>
|
||||
internal class OnlySingleItemsRepositoryCachePolicyFactory<TEntity, TId> : IRepositoryCachePolicyFactory<TEntity, TId>
|
||||
where TEntity : class, IAggregateRoot
|
||||
{
|
||||
private readonly IRuntimeCacheProvider _runtimeCache;
|
||||
private readonly RepositoryCachePolicyOptions _options;
|
||||
|
||||
public OnlySingleItemsRepositoryCachePolicyFactory(IRuntimeCacheProvider runtimeCache, RepositoryCachePolicyOptions options)
|
||||
{
|
||||
_runtimeCache = runtimeCache;
|
||||
_options = options;
|
||||
}
|
||||
|
||||
public virtual IRepositoryCachePolicy<TEntity, TId> CreatePolicy()
|
||||
{
|
||||
return new OnlySingleItemsRepositoryCachePolicy<TEntity, TId>(_runtimeCache, _options);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,34 @@
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
internal class RepositoryCacheOptions
|
||||
internal class RepositoryCachePolicyOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor sets defaults
|
||||
/// Ctor - sets GetAllCacheValidateCount = true
|
||||
/// </summary>
|
||||
public RepositoryCacheOptions()
|
||||
public RepositoryCachePolicyOptions(Func<int> performCount)
|
||||
{
|
||||
PerformCount = performCount;
|
||||
GetAllCacheValidateCount = true;
|
||||
GetAllCacheAllowZeroCount = false;
|
||||
GetAllCacheThresholdLimit = 100;
|
||||
GetAllCacheAsCollection = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ctor - sets GetAllCacheValidateCount = false
|
||||
/// </summary>
|
||||
public RepositoryCachePolicyOptions()
|
||||
{
|
||||
PerformCount = null;
|
||||
GetAllCacheValidateCount = false;
|
||||
GetAllCacheAllowZeroCount = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback required to get count for GetAllCacheValidateCount
|
||||
/// </summary>
|
||||
public Func<int> PerformCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// True/false as to validate the total item count when all items are returned from cache, the default is true but this
|
||||
/// means that a db lookup will occur - though that lookup will probably be significantly less expensive than the normal
|
||||
@@ -22,26 +38,11 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// setting this to return false will improve performance of GetAll cache with no params but should only be used
|
||||
/// for specific circumstances
|
||||
/// </remarks>
|
||||
public bool GetAllCacheValidateCount { get; set; }
|
||||
public bool GetAllCacheValidateCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// True if the GetAll method will cache that there are zero results so that the db is not hit when there are no results found
|
||||
/// </summary>
|
||||
public bool GetAllCacheAllowZeroCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The threshold entity count for which the GetAll method will cache entities
|
||||
/// </summary>
|
||||
public int GetAllCacheThresholdLimit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// When set to true, the cache for the result of GetAll will be cached as a List/Collection rather than
|
||||
/// individual entities in the dictionary
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The default is false which means that if the result of GetAll is less than the GetAllCacheThresholdLimit, each entity
|
||||
/// returned will be cached individually
|
||||
/// </remarks>
|
||||
public bool GetAllCacheAsCollection { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -28,27 +28,19 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
_languageRepository = languageRepository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the repository cache options
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The dictionary repository is also backed by two sub repositories, the main one that will be used is the DictionaryByKeyRepository
|
||||
/// since the queries from DefaultCultureDictionary will use this. That repositories will manage it's own caches by keys.
|
||||
/// </remarks>
|
||||
protected override RepositoryCacheOptions RepositoryCacheOptions
|
||||
private IRepositoryCachePolicyFactory<IDictionaryItem, int> _cachePolicyFactory;
|
||||
protected override IRepositoryCachePolicyFactory<IDictionaryItem, int> CachePolicyFactory
|
||||
{
|
||||
get
|
||||
{
|
||||
return new RepositoryCacheOptions
|
||||
{
|
||||
//If there is zero, we can cache it
|
||||
GetAllCacheAllowZeroCount = true,
|
||||
GetAllCacheAsCollection = false,
|
||||
GetAllCacheValidateCount = false,
|
||||
//dont' cache any result with GetAll - since there could be a ton
|
||||
// of dictionary items.
|
||||
GetAllCacheThresholdLimit = 0
|
||||
};
|
||||
//custom cache policy which will not cache any results for GetAll
|
||||
return _cachePolicyFactory ?? (_cachePolicyFactory = new OnlySingleItemsRepositoryCachePolicyFactory<IDictionaryItem, int>(
|
||||
RuntimeCache,
|
||||
new RepositoryCachePolicyOptions
|
||||
{
|
||||
//allow zero to be cached
|
||||
GetAllCacheAllowZeroCount = true
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,23 +346,19 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return "cmsDictionary." + SqlSyntax.GetQuotedColumnName("id") + " in (@ids)";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the repository cache options
|
||||
/// </summary>
|
||||
protected override RepositoryCacheOptions RepositoryCacheOptions
|
||||
private IRepositoryCachePolicyFactory<IDictionaryItem, Guid> _cachePolicyFactory;
|
||||
protected override IRepositoryCachePolicyFactory<IDictionaryItem, Guid> CachePolicyFactory
|
||||
{
|
||||
get
|
||||
{
|
||||
return new RepositoryCacheOptions
|
||||
{
|
||||
//If there is zero, we can cache it
|
||||
GetAllCacheAllowZeroCount = true,
|
||||
GetAllCacheAsCollection = false,
|
||||
GetAllCacheValidateCount = false,
|
||||
//dont' cache any result with GetAll - since there could be a ton
|
||||
// of dictionary items.
|
||||
GetAllCacheThresholdLimit = 0
|
||||
};
|
||||
//custom cache policy which will not cache any results for GetAll
|
||||
return _cachePolicyFactory ?? (_cachePolicyFactory = new OnlySingleItemsRepositoryCachePolicyFactory<IDictionaryItem, Guid>(
|
||||
RuntimeCache,
|
||||
new RepositoryCachePolicyOptions
|
||||
{
|
||||
//allow zero to be cached
|
||||
GetAllCacheAllowZeroCount = true
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -417,23 +405,19 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return "cmsDictionary." + SqlSyntax.GetQuotedColumnName("key") + " in (@ids)";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the repository cache options
|
||||
/// </summary>
|
||||
protected override RepositoryCacheOptions RepositoryCacheOptions
|
||||
private IRepositoryCachePolicyFactory<IDictionaryItem, string> _cachePolicyFactory;
|
||||
protected override IRepositoryCachePolicyFactory<IDictionaryItem, string> CachePolicyFactory
|
||||
{
|
||||
get
|
||||
{
|
||||
return new RepositoryCacheOptions
|
||||
{
|
||||
//If there is zero, we can cache it
|
||||
GetAllCacheAllowZeroCount = true,
|
||||
GetAllCacheAsCollection = false,
|
||||
GetAllCacheValidateCount = false,
|
||||
//dont' cache any result with GetAll - since there could be a ton
|
||||
// of dictionary items.
|
||||
GetAllCacheThresholdLimit = 0
|
||||
};
|
||||
//custom cache policy which will not cache any results for GetAll
|
||||
return _cachePolicyFactory ?? (_cachePolicyFactory = new OnlySingleItemsRepositoryCachePolicyFactory<IDictionaryItem, string>(
|
||||
RuntimeCache,
|
||||
new RepositoryCachePolicyOptions
|
||||
{
|
||||
//allow zero to be cached
|
||||
GetAllCacheAllowZeroCount = true
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,26 +18,19 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
internal class DomainRepository : PetaPocoRepositoryBase<int, IDomain>, IDomainRepository
|
||||
{
|
||||
private readonly RepositoryCacheOptions _cacheOptions;
|
||||
|
||||
public DomainRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax)
|
||||
: base(work, cache, logger, sqlSyntax)
|
||||
{
|
||||
//Custom cache options for better performance
|
||||
_cacheOptions = new RepositoryCacheOptions
|
||||
{
|
||||
GetAllCacheAllowZeroCount = true,
|
||||
GetAllCacheValidateCount = false,
|
||||
GetAllCacheAsCollection = true
|
||||
};
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the repository cache options
|
||||
/// </summary>
|
||||
protected override RepositoryCacheOptions RepositoryCacheOptions
|
||||
private FullDataSetRepositoryCachePolicyFactory<IDomain, int> _cachePolicyFactory;
|
||||
protected override IRepositoryCachePolicyFactory<IDomain, int> CachePolicyFactory
|
||||
{
|
||||
get { return _cacheOptions; }
|
||||
get
|
||||
{
|
||||
//Use a FullDataSet cache policy - this will cache the entire GetAll result in a single collection
|
||||
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<IDomain, int>(RuntimeCache));
|
||||
}
|
||||
}
|
||||
|
||||
protected override IDomain PerformGet(int id)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
@@ -20,24 +21,17 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
public LanguageRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax)
|
||||
: base(work, cache, logger, sqlSyntax)
|
||||
{
|
||||
//Custom cache options for better performance
|
||||
_cacheOptions = new RepositoryCacheOptions
|
||||
{
|
||||
GetAllCacheAllowZeroCount = true,
|
||||
GetAllCacheValidateCount = false,
|
||||
GetAllCacheAsCollection = true
|
||||
};
|
||||
{
|
||||
}
|
||||
|
||||
private readonly RepositoryCacheOptions _cacheOptions;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the repository cache options
|
||||
/// </summary>
|
||||
protected override RepositoryCacheOptions RepositoryCacheOptions
|
||||
private FullDataSetRepositoryCachePolicyFactory<ILanguage, int> _cachePolicyFactory;
|
||||
protected override IRepositoryCachePolicyFactory<ILanguage, int> CachePolicyFactory
|
||||
{
|
||||
get { return _cacheOptions; }
|
||||
get
|
||||
{
|
||||
//Use a FullDataSet cache policy - this will cache the entire GetAll result in a single collection
|
||||
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<ILanguage, int>(RuntimeCache));
|
||||
}
|
||||
}
|
||||
|
||||
#region Overrides of RepositoryBase<int,Language>
|
||||
|
||||
@@ -17,20 +17,18 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
public PublicAccessRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax)
|
||||
: base(work, cache, logger, sqlSyntax)
|
||||
{
|
||||
_options = new RepositoryCacheOptions
|
||||
{
|
||||
//We want to ensure that a zero count gets cached, even if there is nothing in the db we don't want it to lookup nothing each time
|
||||
GetAllCacheAllowZeroCount = true,
|
||||
//We'll use GetAll as the backing source for all queries and we'll cache the result as a single collection
|
||||
GetAllCacheAsCollection = true,
|
||||
//Override to false so that a Count check against the db is NOT performed when doing a GetAll without params, we just want to
|
||||
// return the raw cache without validation. The GetAll on this repository gets called *A lot*, we want max performance
|
||||
GetAllCacheValidateCount = false
|
||||
};
|
||||
{
|
||||
}
|
||||
|
||||
private readonly RepositoryCacheOptions _options;
|
||||
private FullDataSetRepositoryCachePolicyFactory<PublicAccessEntry, Guid> _cachePolicyFactory;
|
||||
protected override IRepositoryCachePolicyFactory<PublicAccessEntry, Guid> CachePolicyFactory
|
||||
{
|
||||
get
|
||||
{
|
||||
//Use a FullDataSet cache policy - this will cache the entire GetAll result in a single collection
|
||||
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<PublicAccessEntry, Guid>(RuntimeCache));
|
||||
}
|
||||
}
|
||||
|
||||
protected override PublicAccessEntry PerformGet(Guid id)
|
||||
{
|
||||
@@ -94,15 +92,6 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the repository cache options
|
||||
/// </summary>
|
||||
protected override RepositoryCacheOptions RepositoryCacheOptions
|
||||
{
|
||||
get { return _options; }
|
||||
}
|
||||
|
||||
|
||||
protected override void PersistNewItem(PublicAccessEntry entity)
|
||||
{
|
||||
entity.AddingEntity();
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
}
|
||||
|
||||
private readonly RepositoryCacheOptions _cacheOptions = new RepositoryCacheOptions();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The runtime cache used for this repo by default is the isolated cache for this type
|
||||
@@ -92,6 +92,28 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
get { return RepositoryCache.IsolatedRuntimeCache.GetOrCreateCache<TEntity>(); }
|
||||
}
|
||||
|
||||
private IRepositoryCachePolicyFactory<TEntity, TId> _cachePolicyFactory;
|
||||
/// <summary>
|
||||
/// Returns the Cache Policy for the repository
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Cache Policy determines how each entity or entity collection is cached
|
||||
/// </remarks>
|
||||
protected virtual IRepositoryCachePolicyFactory<TEntity, TId> CachePolicyFactory
|
||||
{
|
||||
get
|
||||
{
|
||||
return _cachePolicyFactory ?? (_cachePolicyFactory = new DefaultRepositoryCachePolicyFactory<TEntity, TId>(
|
||||
RuntimeCache,
|
||||
new RepositoryCachePolicyOptions(() =>
|
||||
{
|
||||
//Get count of all entities of current type (TEntity) to ensure cached result is correct
|
||||
var query = Query<TEntity>.Builder.Where(x => x.Id != 0);
|
||||
return PerformCount(query);
|
||||
})));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds or Updates an entity of type TEntity
|
||||
/// </summary>
|
||||
@@ -123,23 +145,16 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
protected abstract TEntity PerformGet(TId id);
|
||||
/// <summary>
|
||||
/// Gets an entity by the passed in Id utilizing the repository's runtime cache
|
||||
/// Gets an entity by the passed in Id utilizing the repository's cache policy
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public TEntity Get(TId id)
|
||||
{
|
||||
var cacheKey = GetCacheIdKey<TEntity>(id);
|
||||
var fromCache = RuntimeCache.GetCacheItem<TEntity>(cacheKey);
|
||||
|
||||
if (fromCache != null) return fromCache;
|
||||
|
||||
var entity = PerformGet(id);
|
||||
if (entity == null) return null;
|
||||
|
||||
RuntimeCache.InsertCacheItem(cacheKey, () => entity);
|
||||
|
||||
return entity;
|
||||
using (var p = CachePolicyFactory.CreatePolicy())
|
||||
{
|
||||
return p.Get(id, PerformGet);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract IEnumerable<TEntity> PerformGetAll(params TId[] ids);
|
||||
@@ -162,110 +177,12 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
throw new InvalidOperationException("Cannot perform a query with more than 2000 parameters");
|
||||
}
|
||||
|
||||
if (ids.Any())
|
||||
using (var p = CachePolicyFactory.CreatePolicy())
|
||||
{
|
||||
var entities = ids.Select(x => RuntimeCache.GetCacheItem<TEntity>(GetCacheIdKey<TEntity>(x))).ToArray();
|
||||
|
||||
if (ids.Count().Equals(entities.Count()) && entities.Any(x => x == null) == false)
|
||||
return entities;
|
||||
}
|
||||
else
|
||||
{
|
||||
TEntity[] allEntities;
|
||||
if (RepositoryCacheOptions.GetAllCacheAsCollection)
|
||||
{
|
||||
var found = RuntimeCache.GetCacheItem<DeepCloneableList<TEntity>>(GetCacheTypeKey<TEntity>());
|
||||
allEntities = found == null ? new TEntity[] {} : found.WhereNotNull().ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
allEntities = RuntimeCache.GetCacheItemsByKeySearch<TEntity>(GetCacheTypeKey<TEntity>())
|
||||
.WhereNotNull()
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
if (allEntities.Any())
|
||||
{
|
||||
|
||||
if (RepositoryCacheOptions.GetAllCacheValidateCount)
|
||||
{
|
||||
//Get count of all entities of current type (TEntity) to ensure cached result is correct
|
||||
var query = Query<TEntity>.Builder.Where(x => x.Id != 0);
|
||||
int totalCount = PerformCount(query);
|
||||
|
||||
if (allEntities.Count() == totalCount)
|
||||
return allEntities;
|
||||
}
|
||||
else
|
||||
{
|
||||
return allEntities;
|
||||
}
|
||||
}
|
||||
else if (RepositoryCacheOptions.GetAllCacheAllowZeroCount)
|
||||
{
|
||||
//if the repository allows caching a zero count, then check the zero count cache
|
||||
var zeroCount = RuntimeCache.GetCacheItem<TEntity[]>(GetCacheTypeKey<TEntity>());
|
||||
if (zeroCount != null && zeroCount.Any() == false)
|
||||
{
|
||||
//there is a zero count cache so return an empty list
|
||||
return Enumerable.Empty<TEntity>();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var entityCollection = PerformGetAll(ids)
|
||||
//ensure we don't include any null refs in the returned collection!
|
||||
.WhereNotNull()
|
||||
.ToArray();
|
||||
|
||||
//This option cannot execute if we are looking up specific Ids
|
||||
if (ids.Any() == false && entityCollection.Length == 0 && RepositoryCacheOptions.GetAllCacheAllowZeroCount)
|
||||
{
|
||||
//there was nothing returned but we want to cache a zero count result so add an TEntity[] to the cache
|
||||
// to signify that there is a zero count cache
|
||||
RuntimeCache.InsertCacheItem(GetCacheTypeKey<TEntity>(), () => new TEntity[] {});
|
||||
return entityCollection;
|
||||
}
|
||||
|
||||
//This option cannot execute if we are looking up specific Ids
|
||||
if (ids.Any() == false && RepositoryCacheOptions.GetAllCacheAsCollection)
|
||||
{
|
||||
//when this is true, we don't want to cache each item individually, we want to cache the result as a single collection
|
||||
RuntimeCache.InsertCacheItem(GetCacheTypeKey<TEntity>(), () => new DeepCloneableList<TEntity>(entityCollection));
|
||||
return entityCollection;
|
||||
}
|
||||
|
||||
if (entityCollection.Length > RepositoryCacheOptions.GetAllCacheThresholdLimit)
|
||||
{
|
||||
//We need to put a threshold here! IF there's an insane amount of items
|
||||
// coming back here we don't want to chuck it all into memory, this added cache here
|
||||
// is more for convenience when paging stuff temporarily
|
||||
return entityCollection;
|
||||
}
|
||||
|
||||
//This is the default behavior, we'll individually cache each item so that if/when these items are resolved
|
||||
// by id, they are returned from the already existing cache.
|
||||
foreach (var entity in entityCollection)
|
||||
{
|
||||
if (entity != null)
|
||||
{
|
||||
var localCopy = entity;
|
||||
RuntimeCache.InsertCacheItem(GetCacheIdKey<TEntity>(entity.Id), () => localCopy);
|
||||
}
|
||||
}
|
||||
|
||||
return entityCollection;
|
||||
return p.GetAll(ids, PerformGetAll);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the repository cache options
|
||||
/// </summary>
|
||||
protected virtual RepositoryCacheOptions RepositoryCacheOptions
|
||||
{
|
||||
get { return _cacheOptions; }
|
||||
}
|
||||
|
||||
|
||||
protected abstract IEnumerable<TEntity> PerformGetByQuery(IQuery<TEntity> query);
|
||||
/// <summary>
|
||||
/// Gets a list of entities by the passed in query
|
||||
@@ -287,12 +204,10 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// <returns></returns>
|
||||
public bool Exists(TId id)
|
||||
{
|
||||
var fromCache = RuntimeCache.GetCacheItem<TEntity>(GetCacheIdKey<TEntity>(id));
|
||||
if (fromCache != null)
|
||||
using (var p = CachePolicyFactory.CreatePolicy())
|
||||
{
|
||||
return true;
|
||||
return p.Exists(id, PerformExists);
|
||||
}
|
||||
return PerformExists(id);
|
||||
}
|
||||
|
||||
protected abstract int PerformCount(IQuery<TEntity> query);
|
||||
@@ -312,23 +227,12 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// <param name="entity"></param>
|
||||
public virtual void PersistNewItem(IEntity entity)
|
||||
{
|
||||
try
|
||||
{
|
||||
PersistNewItem((TEntity)entity);
|
||||
RuntimeCache.InsertCacheItem(GetCacheIdKey<TEntity>(entity.Id), () => entity);
|
||||
//If there's a GetAll zero count cache, ensure it is cleared
|
||||
RuntimeCache.ClearCacheItem(GetCacheTypeKey<TEntity>());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//if an exception is thrown we need to remove the entry from cache, this is ONLY a work around because of the way
|
||||
// that we cache entities: http://issues.umbraco.org/issue/U4-4259
|
||||
RuntimeCache.ClearCacheItem(GetCacheIdKey<TEntity>(entity.Id));
|
||||
//If there's a GetAll zero count cache, ensure it is cleared
|
||||
RuntimeCache.ClearCacheItem(GetCacheTypeKey<TEntity>());
|
||||
throw;
|
||||
}
|
||||
var casted = (TEntity)entity;
|
||||
|
||||
using (var p = CachePolicyFactory.CreatePolicy())
|
||||
{
|
||||
p.CreateOrUpdate(casted, PersistNewItem);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -337,23 +241,12 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// <param name="entity"></param>
|
||||
public virtual void PersistUpdatedItem(IEntity entity)
|
||||
{
|
||||
try
|
||||
{
|
||||
PersistUpdatedItem((TEntity)entity);
|
||||
RuntimeCache.InsertCacheItem(GetCacheIdKey<TEntity>(entity.Id), () => entity);
|
||||
//If there's a GetAll zero count cache, ensure it is cleared
|
||||
RuntimeCache.ClearCacheItem(GetCacheTypeKey<TEntity>());
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//if an exception is thrown we need to remove the entry from cache, this is ONLY a work around because of the way
|
||||
// that we cache entities: http://issues.umbraco.org/issue/U4-4259
|
||||
RuntimeCache.ClearCacheItem(GetCacheIdKey<TEntity>(entity.Id));
|
||||
//If there's a GetAll zero count cache, ensure it is cleared
|
||||
RuntimeCache.ClearCacheItem(GetCacheTypeKey<TEntity>());
|
||||
throw;
|
||||
}
|
||||
var casted = (TEntity)entity;
|
||||
|
||||
using (var p = CachePolicyFactory.CreatePolicy())
|
||||
{
|
||||
p.CreateOrUpdate(casted, PersistUpdatedItem);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -362,10 +255,12 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// <param name="entity"></param>
|
||||
public virtual void PersistDeletedItem(IEntity entity)
|
||||
{
|
||||
PersistDeletedItem((TEntity)entity);
|
||||
RuntimeCache.ClearCacheItem(GetCacheIdKey<TEntity>(entity.Id));
|
||||
//If there's a GetAll zero count cache, ensure it is cleared
|
||||
RuntimeCache.ClearCacheItem(GetCacheTypeKey<TEntity>());
|
||||
var casted = (TEntity)entity;
|
||||
|
||||
using (var p = CachePolicyFactory.CreatePolicy())
|
||||
{
|
||||
p.Remove(casted, PersistDeletedItem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.IO;
|
||||
@@ -32,7 +33,6 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
private readonly ITemplatesSection _templateConfig;
|
||||
private readonly ViewHelper _viewHelper;
|
||||
private readonly MasterPageHelper _masterPageHelper;
|
||||
private readonly RepositoryCacheOptions _cacheOptions;
|
||||
|
||||
internal TemplateRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IFileSystem masterpageFileSystem, IFileSystem viewFileSystem, ITemplatesSection templateConfig)
|
||||
: base(work, cache, logger, sqlSyntax)
|
||||
@@ -41,25 +41,18 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
_viewsFileSystem = viewFileSystem;
|
||||
_templateConfig = templateConfig;
|
||||
_viewHelper = new ViewHelper(_viewsFileSystem);
|
||||
_masterPageHelper = new MasterPageHelper(_masterpagesFileSystem);
|
||||
|
||||
_cacheOptions = new RepositoryCacheOptions
|
||||
{
|
||||
//Allow a zero count cache entry because GetAll() gets used quite a lot and we want to ensure
|
||||
// if there are no templates, that it doesn't keep going to the db.
|
||||
GetAllCacheAllowZeroCount = true,
|
||||
//GetAll is used as the base call for getting all templates, so we'll cache it as a single entry
|
||||
GetAllCacheAsCollection = true
|
||||
};
|
||||
_masterPageHelper = new MasterPageHelper(_masterpagesFileSystem);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the repository cache options
|
||||
/// </summary>
|
||||
protected override RepositoryCacheOptions RepositoryCacheOptions
|
||||
private FullDataSetRepositoryCachePolicyFactory<ITemplate, int> _cachePolicyFactory;
|
||||
protected override IRepositoryCachePolicyFactory<ITemplate, int> CachePolicyFactory
|
||||
{
|
||||
get { return _cacheOptions; }
|
||||
get
|
||||
{
|
||||
//Use a FullDataSet cache policy - this will cache the entire GetAll result in a single collection
|
||||
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<ITemplate, int>(RuntimeCache));
|
||||
}
|
||||
}
|
||||
|
||||
#region Overrides of RepositoryBase<int,ITemplate>
|
||||
|
||||
@@ -156,12 +156,18 @@
|
||||
<Compile Include="CacheHelper.cs" />
|
||||
<Compile Include="Cache\CacheKeys.cs" />
|
||||
<Compile Include="Cache\CacheProviderExtensions.cs" />
|
||||
<Compile Include="Cache\DefaultRepositoryCachePolicy.cs" />
|
||||
<Compile Include="Cache\DefaultRepositoryCachePolicyFactory.cs" />
|
||||
<Compile Include="Cache\FullDataSetRepositoryCachePolicy.cs" />
|
||||
<Compile Include="Cache\FullDataSetRepositoryCachePolicyFactory.cs" />
|
||||
<Compile Include="Cache\ICacheProvider.cs" />
|
||||
<Compile Include="Cache\CacheRefresherBase.cs" />
|
||||
<Compile Include="Cache\CacheRefresherEventArgs.cs" />
|
||||
<Compile Include="Cache\DictionaryCacheProviderBase.cs" />
|
||||
<Compile Include="Cache\HttpRequestCacheProvider.cs" />
|
||||
<Compile Include="Cache\IRepositoryCachePolicy.cs" />
|
||||
<Compile Include="Cache\IPayloadCacheRefresher.cs" />
|
||||
<Compile Include="Cache\IRepositoryCachePolicyFactory.cs" />
|
||||
<Compile Include="Cache\IsolatedRuntimeCache.cs" />
|
||||
<Compile Include="Cache\ObjectCacheRuntimeCacheProvider.cs" />
|
||||
<Compile Include="Cache\IRuntimeCacheProvider.cs" />
|
||||
@@ -169,7 +175,10 @@
|
||||
<Compile Include="Cache\IJsonCacheRefresher.cs" />
|
||||
<Compile Include="Cache\JsonCacheRefresherBase.cs" />
|
||||
<Compile Include="Cache\NullCacheProvider.cs" />
|
||||
<Compile Include="Cache\OnlySingleItemsRepositoryCachePolicy.cs" />
|
||||
<Compile Include="Cache\OnlySingleItemsRepositoryCachePolicyFactory.cs" />
|
||||
<Compile Include="Cache\PayloadCacheRefresherBase.cs" />
|
||||
<Compile Include="Cache\RepositoryCachePolicyOptions.cs" />
|
||||
<Compile Include="Cache\StaticCacheProvider.cs" />
|
||||
<Compile Include="Cache\TypedCacheRefresherBase.cs" />
|
||||
<Compile Include="CodeAnnotations\FriendlyNameAttribute.cs" />
|
||||
@@ -457,7 +466,6 @@
|
||||
<Compile Include="Persistence\Repositories\Interfaces\ITaskTypeRepository.cs" />
|
||||
<Compile Include="Persistence\Repositories\MigrationEntryRepository.cs" />
|
||||
<Compile Include="Persistence\Repositories\PublicAccessRepository.cs" />
|
||||
<Compile Include="Persistence\Repositories\RepositoryCacheOptions.cs" />
|
||||
<Compile Include="Persistence\Repositories\TaskRepository.cs" />
|
||||
<Compile Include="Persistence\Repositories\TaskTypeRepository.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\GridValueConverter.cs" />
|
||||
|
||||
Reference in New Issue
Block a user