diff --git a/src/Umbraco.Core/Cache/CacheKeys.cs b/src/Umbraco.Core/Cache/CacheKeys.cs
index f76ff0439f..43a5ec04aa 100644
--- a/src/Umbraco.Core/Cache/CacheKeys.cs
+++ b/src/Umbraco.Core/Cache/CacheKeys.cs
@@ -29,6 +29,8 @@ namespace Umbraco.Core.Cache
public const string MemberBusinessLogicCacheKey = "MemberCacheItem_";
public const string TemplateFrontEndCacheKey = "template";
+
+ [Obsolete("This is no longer used and will be removed from the codebase in the future")]
public const string TemplateBusinessLogicCacheKey = "UmbracoTemplateCache";
public const string UserContextCacheKey = "UmbracoUserContext";
diff --git a/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs b/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs
index 542d85d42d..295ff8b408 100644
--- a/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs
@@ -18,8 +18,20 @@ 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,
+ //Set to 1000 just to ensure that all of them are cached, The GetAll on this repository gets called *A lot*, we want max performance
+ GetAllCacheThresholdLimit = 1000,
+ //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;
+
protected override PublicAccessEntry PerformGet(Guid id)
{
var sql = GetBaseQuery(false);
@@ -91,27 +103,13 @@ namespace Umbraco.Core.Persistence.Repositories
}
///
- /// The threshold entity count for which the GetAll method will cache entities
+ /// Returns the repository cache options
///
- ///
- /// Set to 1000 just to ensure that all of them are cached, The GetAll on this repository gets called *A lot*, we want max performance
- ///
- protected override int GetAllThresholdCacheLimit
+ protected override RepositoryCacheOptions RepositoryCacheOptions
{
- get { return 1000; }
+ get { return _options; }
}
- ///
- /// 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
- ///
- protected override bool GetAllValidateCount
- {
- get { return false; }
- }
protected override void PersistNewItem(PublicAccessEntry entity)
{
diff --git a/src/Umbraco.Core/Persistence/Repositories/RepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/RepositoryBase.cs
index 880756bf6c..0d3c7db7a7 100644
--- a/src/Umbraco.Core/Persistence/Repositories/RepositoryBase.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/RepositoryBase.cs
@@ -80,6 +80,8 @@ namespace Umbraco.Core.Persistence.Repositories
{
}
+ private readonly RepositoryCacheOptions _cacheOptions = new RepositoryCacheOptions();
+
#region IRepository Members
///
@@ -158,18 +160,20 @@ namespace Umbraco.Core.Persistence.Repositories
if (ids.Any())
{
var entities = ids.Select(x => RuntimeCache.GetCacheItem(GetCacheIdKey(x))).ToArray();
-
+
if (ids.Count().Equals(entities.Count()) && entities.Any(x => x == null) == false)
return entities;
}
else
{
- var allEntities = RuntimeCache.GetCacheItemsByKeySearch(GetCacheTypeKey()).ToArray();
+ var allEntities = RuntimeCache.GetCacheItemsByKeySearch(GetCacheTypeKey())
+ .WhereNotNull()
+ .ToArray();
if (allEntities.Any())
{
- if (GetAllValidateCount)
+ if (RepositoryCacheOptions.GetAllCacheValidateCount)
{
//Get count of all entities of current type (TEntity) to ensure cached result is correct
var query = Query.Builder.Where(x => x.Id != 0);
@@ -183,6 +187,17 @@ namespace Umbraco.Core.Persistence.Repositories
return allEntities;
}
}
+ else if (RepositoryCacheOptions.GetAllCacheAllowZeroCount)
+ {
+ //if the repository allows caching a zero count, then check the zero count cache
+ var zeroCount = RuntimeCache.GetCacheItem(GetCacheTypeKey());
+ if (zeroCount != null && zeroCount.Any() == false)
+ {
+ //there is a zero count cache so return an empty list
+ return Enumerable.Empty();
+ }
+ }
+
}
var entityCollection = PerformGetAll(ids)
@@ -194,7 +209,15 @@ namespace Umbraco.Core.Persistence.Repositories
// 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
- if (entityCollection.Length > GetAllThresholdCacheLimit) return entityCollection;
+ if (entityCollection.Length > RepositoryCacheOptions.GetAllCacheThresholdLimit)
+ return entityCollection;
+
+ if (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(), () => new TEntity[] {});
+ }
foreach (var entity in entityCollection)
{
@@ -209,25 +232,11 @@ namespace Umbraco.Core.Persistence.Repositories
}
///
- /// 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
- /// GetAll method.
+ /// Returns the repository cache options
///
- ///
- /// Overriding this to return false will improve performance of GetAll cache with no params but should only be used
- /// for specific circumstances
- ///
- protected virtual bool GetAllValidateCount
+ protected virtual RepositoryCacheOptions RepositoryCacheOptions
{
- get { return true; }
- }
-
- ///
- /// The threshold entity count for which the GetAll method will cache entities
- ///
- protected virtual int GetAllThresholdCacheLimit
- {
- get { return 100; }
+ get { return _cacheOptions; }
}
protected abstract IEnumerable PerformGetByQuery(IQuery query);
@@ -284,12 +293,16 @@ namespace Umbraco.Core.Persistence.Repositories
{
PersistNewItem((TEntity)entity);
RuntimeCache.InsertCacheItem(GetCacheIdKey(entity.Id), () => entity);
+ //If there's a GetAll zero count cache, ensure it is cleared
+ RuntimeCache.ClearCacheItem(GetCacheTypeKey());
}
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(entity.Id));
+ //If there's a GetAll zero count cache, ensure it is cleared
+ RuntimeCache.ClearCacheItem(GetCacheTypeKey());
throw;
}
@@ -305,13 +318,16 @@ namespace Umbraco.Core.Persistence.Repositories
{
PersistUpdatedItem((TEntity)entity);
RuntimeCache.InsertCacheItem(GetCacheIdKey(entity.Id), () => entity);
+ //If there's a GetAll zero count cache, ensure it is cleared
+ RuntimeCache.ClearCacheItem(GetCacheTypeKey());
}
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
- //RepositoryCache.Delete(typeof(TEntity), entity);
RuntimeCache.ClearCacheItem(GetCacheIdKey(entity.Id));
+ //If there's a GetAll zero count cache, ensure it is cleared
+ RuntimeCache.ClearCacheItem(GetCacheTypeKey());
throw;
}
@@ -325,6 +341,8 @@ namespace Umbraco.Core.Persistence.Repositories
{
PersistDeletedItem((TEntity)entity);
RuntimeCache.ClearCacheItem(GetCacheIdKey(entity.Id));
+ //If there's a GetAll zero count cache, ensure it is cleared
+ RuntimeCache.ClearCacheItem(GetCacheTypeKey());
}
#endregion
diff --git a/src/Umbraco.Core/Persistence/Repositories/RepositoryCacheOptions.cs b/src/Umbraco.Core/Persistence/Repositories/RepositoryCacheOptions.cs
new file mode 100644
index 0000000000..9ac8aa6abd
--- /dev/null
+++ b/src/Umbraco.Core/Persistence/Repositories/RepositoryCacheOptions.cs
@@ -0,0 +1,36 @@
+namespace Umbraco.Core.Persistence.Repositories
+{
+ internal class RepositoryCacheOptions
+ {
+ ///
+ /// Constructor sets defaults
+ ///
+ public RepositoryCacheOptions()
+ {
+ GetAllCacheValidateCount = true;
+ GetAllCacheAllowZeroCount = false;
+ GetAllCacheThresholdLimit = 100;
+ }
+
+ ///
+ /// 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
+ /// GetAll method.
+ ///
+ ///
+ /// setting this to return false will improve performance of GetAll cache with no params but should only be used
+ /// for specific circumstances
+ ///
+ public bool GetAllCacheValidateCount { get; set; }
+
+ ///
+ /// 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
+ ///
+ public bool GetAllCacheAllowZeroCount { get; set; }
+
+ ///
+ /// The threshold entity count for which the GetAll method will cache entities
+ ///
+ public int GetAllCacheThresholdLimit { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Persistence/RepositoryFactory.cs b/src/Umbraco.Core/Persistence/RepositoryFactory.cs
index d6f2a0f80e..be6d35ca27 100644
--- a/src/Umbraco.Core/Persistence/RepositoryFactory.cs
+++ b/src/Umbraco.Core/Persistence/RepositoryFactory.cs
@@ -80,7 +80,9 @@ namespace Umbraco.Core.Persistence
public virtual IAuditRepository CreateAuditRepository(IDatabaseUnitOfWork uow)
{
- return new AuditRepository(uow, _cacheHelper, _logger, _sqlSyntax);
+ return new AuditRepository(uow,
+ CacheHelper.CreateDisabledCacheHelper(), //never cache
+ _logger, _sqlSyntax);
}
public virtual ITagRepository CreateTagRepository(IDatabaseUnitOfWork uow)
diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj
index 02c14d375c..3419ba2517 100644
--- a/src/Umbraco.Core/Umbraco.Core.csproj
+++ b/src/Umbraco.Core/Umbraco.Core.csproj
@@ -346,6 +346,7 @@
+
diff --git a/src/Umbraco.Web/Cache/DomainCacheRefresher.cs b/src/Umbraco.Web/Cache/DomainCacheRefresher.cs
index 11f8291e6c..aabe95548f 100644
--- a/src/Umbraco.Web/Cache/DomainCacheRefresher.cs
+++ b/src/Umbraco.Web/Cache/DomainCacheRefresher.cs
@@ -1,6 +1,7 @@
using System;
using Umbraco.Core;
using Umbraco.Core.Cache;
+using Umbraco.Core.Persistence.Repositories;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.PublishedCache.XmlPublishedCache;
@@ -40,6 +41,8 @@ namespace Umbraco.Web.Cache
private void ClearCache()
{
+ ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes();
+
// SD: we need to clear the routes cache here!
//
// zpqrtbnk: no, not here, in fact the caches should subsribe to refresh events else we
diff --git a/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs b/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs
index 5ef1fbf468..6270abe7e6 100644
--- a/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs
+++ b/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs
@@ -55,9 +55,6 @@ namespace Umbraco.Web.Cache
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(
string.Format("{0}{1}", CacheKeys.TemplateFrontEndCacheKey, id));
- ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(
- string.Format("{0}{1}", CacheKeys.TemplateBusinessLogicCacheKey, id));
-
//need to clear the runtime cache for template instances
//NOTE: This is temp until we implement the correct ApplicationCache and then we can remove the RuntimeCache, etc...
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes();
diff --git a/src/Umbraco.Web/umbraco.presentation/template.cs b/src/Umbraco.Web/umbraco.presentation/template.cs
index 40a786325a..cf1186867c 100644
--- a/src/Umbraco.Web/umbraco.presentation/template.cs
+++ b/src/Umbraco.Web/umbraco.presentation/template.cs
@@ -24,7 +24,7 @@ namespace umbraco
///
/// Holds methods for parsing and building umbraco templates
///
- ///
+ [Obsolete("Do not use this class, use Umbraco.Core.Service.IFileService to work with templates")]
public class template
{
#region private variables