From bf65bf5bab539b16db83d3539f6a4f8f2b50142e Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 17 Apr 2014 14:23:37 +1000 Subject: [PATCH] Got pre-values caching properly and data types using the runtime cache provider correctly + unit tests. --- src/Umbraco.Core/Cache/CacheKeys.cs | 1 + .../Cache/CacheProviderExtensions.cs | 6 + .../Cache/DictionaryCacheProviderBase.cs | 20 +++ src/Umbraco.Core/Cache/ICacheProvider.cs | 8 ++ src/Umbraco.Core/Cache/NullCacheProvider.cs | 5 + .../Cache/ObjectCacheRuntimeCacheProvider.cs | 7 + src/Umbraco.Core/Cache/StaticCacheProvider.cs | 7 + .../DataTypeDefinitionRepository.cs | 93 +++++++++++- .../IDataTypeDefinitionRepository.cs | 3 +- .../Persistence/RepositoryFactory.cs | 5 +- src/Umbraco.Core/Services/DataTypeService.cs | 19 ++- src/Umbraco.Core/StringExtensions.cs | 9 ++ .../DataTypeDefinitionRepositoryTest.cs | 135 +++++++++++++++++- .../Cache/DataTypeCacheRefresher.cs | 10 +- 14 files changed, 307 insertions(+), 21 deletions(-) diff --git a/src/Umbraco.Core/Cache/CacheKeys.cs b/src/Umbraco.Core/Cache/CacheKeys.cs index 1278ff0e33..c1f82b0d89 100644 --- a/src/Umbraco.Core/Cache/CacheKeys.cs +++ b/src/Umbraco.Core/Cache/CacheKeys.cs @@ -53,5 +53,6 @@ namespace Umbraco.Core.Cache public const string StylesheetPropertyCacheKey = "UmbracoStylesheetProperty"; public const string DataTypeCacheKey = "UmbracoDataTypeDefinition"; + public const string DataTypePreValuesCacheKey = "UmbracoPreVal"; } } \ No newline at end of file diff --git a/src/Umbraco.Core/Cache/CacheProviderExtensions.cs b/src/Umbraco.Core/Cache/CacheProviderExtensions.cs index 7b621d013f..dc05d88e22 100644 --- a/src/Umbraco.Core/Cache/CacheProviderExtensions.cs +++ b/src/Umbraco.Core/Cache/CacheProviderExtensions.cs @@ -41,6 +41,12 @@ namespace Umbraco.Core.Cache return result.Select(x => x.TryConvertTo().Result); } + public static IEnumerable GetCacheItemsByKeyExpression(this ICacheProvider provider, string regexString) + { + var result = provider.GetCacheItemsByKeyExpression(regexString); + return result.Select(x => x.TryConvertTo().Result); + } + public static T GetCacheItem(this ICacheProvider provider, string cacheKey) { var result = provider.GetCacheItem(cacheKey); diff --git a/src/Umbraco.Core/Cache/DictionaryCacheProviderBase.cs b/src/Umbraco.Core/Cache/DictionaryCacheProviderBase.cs index e38dee57c4..9de7ac25fa 100644 --- a/src/Umbraco.Core/Cache/DictionaryCacheProviderBase.cs +++ b/src/Umbraco.Core/Cache/DictionaryCacheProviderBase.cs @@ -171,6 +171,26 @@ namespace Umbraco.Core.Cache select c.Value).ToList(); } + public IEnumerable GetCacheItemsByKeyExpression(string regexString) + { + var found = new List(); + foreach (var item in DictionaryCache) + { + var c = new DictionaryItemWrapper(item); + var s = c.Key as string; + if (s != null) + { + var withoutPrefix = s.TrimStart(string.Format("{0}-", CacheItemPrefix)); + if (Regex.IsMatch(withoutPrefix, regexString)) + { + found.Add(c.Value); + } + } + } + + return found; + } + /// /// Returns a cache item by key, does not update the cache if it isn't there. /// diff --git a/src/Umbraco.Core/Cache/ICacheProvider.cs b/src/Umbraco.Core/Cache/ICacheProvider.cs index e9bdde3ff2..4ee95c0063 100644 --- a/src/Umbraco.Core/Cache/ICacheProvider.cs +++ b/src/Umbraco.Core/Cache/ICacheProvider.cs @@ -16,7 +16,15 @@ namespace Umbraco.Core.Cache void ClearCacheByKeySearch(string keyStartsWith); void ClearCacheByKeyExpression(string regexString); IEnumerable GetCacheItemsByKeySearch(string keyStartsWith); + IEnumerable GetCacheItemsByKeyExpression(string regexString); + + /// + /// Returns an item with a given key + /// + /// + /// object GetCacheItem(string cacheKey); + object GetCacheItem(string cacheKey, Func getCacheItem); } } \ No newline at end of file diff --git a/src/Umbraco.Core/Cache/NullCacheProvider.cs b/src/Umbraco.Core/Cache/NullCacheProvider.cs index ba88637661..f4e449499b 100644 --- a/src/Umbraco.Core/Cache/NullCacheProvider.cs +++ b/src/Umbraco.Core/Cache/NullCacheProvider.cs @@ -43,6 +43,11 @@ namespace Umbraco.Core.Cache return Enumerable.Empty(); } + public IEnumerable GetCacheItemsByKeyExpression(string regexString) + { + return Enumerable.Empty(); + } + public virtual object GetCacheItem(string cacheKey) { return default(object); diff --git a/src/Umbraco.Core/Cache/ObjectCacheRuntimeCacheProvider.cs b/src/Umbraco.Core/Cache/ObjectCacheRuntimeCacheProvider.cs index aa6a5bbb22..b8e1b6baef 100644 --- a/src/Umbraco.Core/Cache/ObjectCacheRuntimeCacheProvider.cs +++ b/src/Umbraco.Core/Cache/ObjectCacheRuntimeCacheProvider.cs @@ -114,6 +114,13 @@ namespace Umbraco.Core.Cache select c.Value).ToList(); } + public IEnumerable GetCacheItemsByKeyExpression(string regexString) + { + return (from c in MemoryCache + where Regex.IsMatch(c.Key, regexString) + select c.Value).ToList(); + } + public virtual object GetCacheItem(string cacheKey) { var result = MemoryCache.Get(cacheKey); diff --git a/src/Umbraco.Core/Cache/StaticCacheProvider.cs b/src/Umbraco.Core/Cache/StaticCacheProvider.cs index cd58fc3dde..9c448efa6a 100644 --- a/src/Umbraco.Core/Cache/StaticCacheProvider.cs +++ b/src/Umbraco.Core/Cache/StaticCacheProvider.cs @@ -59,6 +59,13 @@ namespace Umbraco.Core.Cache select c.Value).ToList(); } + public IEnumerable GetCacheItemsByKeyExpression(string regexString) + { + return (from KeyValuePair c in StaticCache + where Regex.IsMatch(c.Key, regexString) + select c.Value).ToList(); + } + public virtual object GetCacheItem(string cacheKey) { var result = StaticCache[cacheKey]; diff --git a/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs b/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs index 3798bb53d9..423802fbb5 100644 --- a/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.Data; using System.Globalization; using System.Linq; +using System.Threading; +using Umbraco.Core.Cache; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; @@ -11,6 +13,7 @@ using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Services; namespace Umbraco.Core.Persistence.Repositories { @@ -19,16 +22,22 @@ namespace Umbraco.Core.Persistence.Repositories /// internal class DataTypeDefinitionRepository : PetaPocoRepositoryBase, IDataTypeDefinitionRepository { - public DataTypeDefinitionRepository(IDatabaseUnitOfWork work) + private readonly CacheHelper _cacheHelper; + + public DataTypeDefinitionRepository(IDatabaseUnitOfWork work, CacheHelper cacheHelper) : base(work) { + _cacheHelper = cacheHelper; } - public DataTypeDefinitionRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache) + public DataTypeDefinitionRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, CacheHelper cacheHelper) : base(work, cache) { + _cacheHelper = cacheHelper; } + private readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(); + #region Overrides of RepositoryBase protected override IDataTypeDefinition PerformGet(int id) @@ -238,5 +247,85 @@ AND umbracoNode.id <> @id", } #endregion + + public PreValueCollection GetPreValuesCollectionByDataTypeId(int dataTypeId) + { + using (var l = new UpgradeableReadLock(Locker)) + { + var cached = _cacheHelper.RuntimeCache.GetCacheItemsByKeySearch(GetPrefixedCacheKey(dataTypeId)); + if (cached != null && cached.Any()) + { + //return from the cache + return cached.First(); + } + + l.UpgradeToWriteLock(); + + return GetAndCachePreValueCollection(dataTypeId); + } + } + + public string GetPreValueAsString(int preValueId) + { + using (var l = new UpgradeableReadLock(Locker)) + { + //We need to see if we can find the cached PreValueCollection based on the cache key above + + var regex = CacheKeys.DataTypePreValuesCacheKey + @"[\d]+-[,\d]*" + preValueId + @"[,\d$]*"; + + var cached = _cacheHelper.RuntimeCache.GetCacheItemsByKeyExpression(regex); + if (cached != null && cached.Any()) + { + //return from the cache + var collection = cached.First(); + var preVal = collection.PreValuesAsArray.Single(x => x.Id == preValueId); + return preVal.Value; + } + + l.UpgradeToWriteLock(); + + //go and find the data type id for the pre val id passed in + + var dto = Database.FirstOrDefault("WHERE id = @preValueId", new { preValueId = preValueId }); + if (dto == null) + { + return string.Empty; + } + // go cache the collection + var preVals = GetAndCachePreValueCollection(dto.DataTypeNodeId); + + //return the single value for this id + var pv = preVals.PreValuesAsArray.Single(x => x.Id == preValueId); + return pv.Value; + } + } + + private string GetPrefixedCacheKey(int dataTypeId) + { + return CacheKeys.DataTypePreValuesCacheKey + dataTypeId + "-"; + } + + private PreValueCollection GetAndCachePreValueCollection(int dataTypeId) + { + //go get the data + var dtos = Database.Fetch("WHERE datatypeNodeId = @Id", new { Id = dataTypeId }); + var list = dtos.Select(x => new Tuple(new PreValue(x.Id, x.Value), x.Alias, x.SortOrder)).ToList(); + var collection = DataTypeService.PreValueConverter.ConvertToPreValuesCollection(list); + + //now create the cache key, this needs to include all pre-value ids so that we can use this cached item in the GetPreValuesAsString method + //the key will be: "UmbracoPreValDATATYPEID-CSVOFPREVALIDS + + var key = GetPrefixedCacheKey(dataTypeId) + + string.Join(",", collection.FormatAsDictionary().Select(x => x.Value.Id).ToArray()); + + //store into cache + _cacheHelper.RuntimeCache.InsertCacheItem(key, () => collection, + //30 mins + new TimeSpan(0, 0, 30), + //sliding is true + true); + + return collection; + } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IDataTypeDefinitionRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IDataTypeDefinitionRepository.cs index 7a39a2cdc1..77fe5edc89 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IDataTypeDefinitionRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IDataTypeDefinitionRepository.cs @@ -4,6 +4,7 @@ namespace Umbraco.Core.Persistence.Repositories { public interface IDataTypeDefinitionRepository : IRepositoryQueryable { - + PreValueCollection GetPreValuesCollectionByDataTypeId(int dataTypeId); + string GetPreValueAsString(int preValueId); } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/RepositoryFactory.cs b/src/Umbraco.Core/Persistence/RepositoryFactory.cs index 627a317202..39488dd951 100644 --- a/src/Umbraco.Core/Persistence/RepositoryFactory.cs +++ b/src/Umbraco.Core/Persistence/RepositoryFactory.cs @@ -55,14 +55,15 @@ namespace Umbraco.Core.Persistence return new ContentTypeRepository( uow, _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current, - new TemplateRepository(uow, NullCacheProvider.Current)); + CreateTemplateRepository(uow)); } public virtual IDataTypeDefinitionRepository CreateDataTypeDefinitionRepository(IDatabaseUnitOfWork uow) { return new DataTypeDefinitionRepository( uow, - NullCacheProvider.Current); + _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current, + _cacheHelper); } public virtual IDictionaryRepository CreateDictionaryRepository(IDatabaseUnitOfWork uow) diff --git a/src/Umbraco.Core/Services/DataTypeService.cs b/src/Umbraco.Core/Services/DataTypeService.cs index 8a1e41a707..45bb7016ef 100644 --- a/src/Umbraco.Core/Services/DataTypeService.cs +++ b/src/Umbraco.Core/Services/DataTypeService.cs @@ -108,10 +108,11 @@ namespace Umbraco.Core.Services /// An enumerable list of string values public IEnumerable GetPreValuesByDataTypeId(int id) { - using (var uow = _uowProvider.GetUnitOfWork()) + using (var repository = _repositoryFactory.CreateDataTypeDefinitionRepository(_uowProvider.GetUnitOfWork())) { - var dtos = uow.Database.Fetch("WHERE datatypeNodeId = @Id", new { Id = id }); - var list = dtos.Select(x => x.Value).ToList(); + var collection = repository.GetPreValuesCollectionByDataTypeId(id); + //now convert the collection to a string list + var list = collection.PreValuesAsArray.Select(x => x.Value).ToList(); return list; } } @@ -123,12 +124,9 @@ namespace Umbraco.Core.Services /// public PreValueCollection GetPreValuesCollectionByDataTypeId(int id) { - using (var uow = _uowProvider.GetUnitOfWork()) + using (var repository = _repositoryFactory.CreateDataTypeDefinitionRepository(_uowProvider.GetUnitOfWork())) { - var dtos = uow.Database.Fetch("WHERE datatypeNodeId = @Id", new { Id = id }); - var list = dtos.Select(x => new Tuple(new PreValue(x.Id, x.Value), x.Alias, x.SortOrder)).ToList(); - - return PreValueConverter.ConvertToPreValuesCollection(list); + return repository.GetPreValuesCollectionByDataTypeId(id); } } @@ -139,10 +137,9 @@ namespace Umbraco.Core.Services /// PreValue as a string public string GetPreValueAsString(int id) { - using (var uow = _uowProvider.GetUnitOfWork()) + using (var repository = _repositoryFactory.CreateDataTypeDefinitionRepository(_uowProvider.GetUnitOfWork())) { - var dto = uow.Database.FirstOrDefault("WHERE id = @Id", new { Id = id }); - return dto != null ? dto.Value : string.Empty; + return repository.GetPreValueAsString(id); } } diff --git a/src/Umbraco.Core/StringExtensions.cs b/src/Umbraco.Core/StringExtensions.cs index 5864b9d159..18a3136c8f 100644 --- a/src/Umbraco.Core/StringExtensions.cs +++ b/src/Umbraco.Core/StringExtensions.cs @@ -1190,5 +1190,14 @@ namespace Umbraco.Core return false; } + public static bool CsvContains(this string csv, string value) + { + if (string.IsNullOrEmpty(csv)) + { + return false; + } + var idCheckList = csv.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries); + return idCheckList.Contains(value); + } } } diff --git a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs index 7d828dfc48..6fc1d19181 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs @@ -3,14 +3,16 @@ using System.Data; using System.Linq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; +using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Caching; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Tests.TestHelpers; +using NullCacheProvider = Umbraco.Core.Persistence.Caching.NullCacheProvider; namespace Umbraco.Tests.Persistence.Repositories { @@ -26,7 +28,7 @@ namespace Umbraco.Tests.Persistence.Repositories private DataTypeDefinitionRepository CreateRepository(IDatabaseUnitOfWork unitOfWork) { - var dataTypeDefinitionRepository = new DataTypeDefinitionRepository(unitOfWork, NullCacheProvider.Current); + var dataTypeDefinitionRepository = new DataTypeDefinitionRepository(unitOfWork, NullCacheProvider.Current, CacheHelper.CreateDisabledCacheHelper()); return dataTypeDefinitionRepository; } @@ -302,6 +304,135 @@ namespace Umbraco.Tests.Persistence.Repositories } } + [Test] + public void Can_Get_Pre_Value_Collection() + { + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + + int dtid; + using (var repository = CreateRepository(unitOfWork)) + { + var dataTypeDefinition = new DataTypeDefinition(-1, new Guid(Constants.PropertyEditors.RadioButtonList)) { Name = "test" }; + repository.AddOrUpdate(dataTypeDefinition); + unitOfWork.Commit(); + dtid = dataTypeDefinition.Id; + } + + DatabaseContext.Database.Insert(new DataTypePreValueDto() { DataTypeNodeId = dtid, SortOrder = 0, Value = "test1"}); + DatabaseContext.Database.Insert(new DataTypePreValueDto() { DataTypeNodeId = dtid, SortOrder = 1, Value = "test2" }); + + using (var repository = CreateRepository(unitOfWork)) + { + var collection = repository.GetPreValuesCollectionByDataTypeId(dtid); + Assert.AreEqual(2, collection.PreValuesAsArray.Count()); + } + } + + [Test] + public void Can_Get_Pre_Value_As_String() + { + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + + int dtid; + using (var repository = CreateRepository(unitOfWork)) + { + var dataTypeDefinition = new DataTypeDefinition(-1, new Guid(Constants.PropertyEditors.RadioButtonList)) { Name = "test" }; + repository.AddOrUpdate(dataTypeDefinition); + unitOfWork.Commit(); + dtid = dataTypeDefinition.Id; + } + + var id = DatabaseContext.Database.Insert(new DataTypePreValueDto() { DataTypeNodeId = dtid, SortOrder = 0, Value = "test1" }); + DatabaseContext.Database.Insert(new DataTypePreValueDto() { DataTypeNodeId = dtid, SortOrder = 1, Value = "test2" }); + + using (var repository = CreateRepository(unitOfWork)) + { + var val = repository.GetPreValueAsString(Convert.ToInt32(id)); + Assert.AreEqual("test1", val); + } + } + + [Test] + public void Can_Get_Pre_Value_Collection_With_Cache() + { + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + + var cache = new CacheHelper(new ObjectCacheRuntimeCacheProvider(), new StaticCacheProvider(), new StaticCacheProvider()); + + Func creator = () => new DataTypeDefinitionRepository( + unitOfWork, + NullCacheProvider.Current, cache); + + DataTypeDefinition dtd; + using (var repository = creator()) + { + dtd = new DataTypeDefinition(-1, new Guid(Constants.PropertyEditors.RadioButtonList)) { Name = "test" }; + repository.AddOrUpdate(dtd); + unitOfWork.Commit(); + } + + DatabaseContext.Database.Insert(new DataTypePreValueDto() { DataTypeNodeId = dtd.Id, SortOrder = 0, Value = "test1" }); + DatabaseContext.Database.Insert(new DataTypePreValueDto() { DataTypeNodeId = dtd.Id, SortOrder = 1, Value = "test2" }); + + //this will cache the result + using (var repository = creator()) + { + var collection = repository.GetPreValuesCollectionByDataTypeId(dtd.Id); + } + + var cached = cache.RuntimeCache.GetCacheItemsByKeySearch(CacheKeys.DataTypePreValuesCacheKey + dtd.Id + "-"); + + Assert.IsNotNull(cached); + Assert.AreEqual(1, cached.Count()); + Assert.AreEqual(2, cached.Single().FormatAsDictionary().Count); + } + + [Test] + public void Can_Get_Pre_Value_As_String_With_Cache() + { + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + + var cache = new CacheHelper(new ObjectCacheRuntimeCacheProvider(), new StaticCacheProvider(), new StaticCacheProvider()); + + Func creator = () => new DataTypeDefinitionRepository( + unitOfWork, + NullCacheProvider.Current, cache); + + DataTypeDefinition dtd; + using (var repository = creator()) + { + dtd = new DataTypeDefinition(-1, new Guid(Constants.PropertyEditors.RadioButtonList)) { Name = "test" }; + repository.AddOrUpdate(dtd); + unitOfWork.Commit(); + } + + var id = DatabaseContext.Database.Insert(new DataTypePreValueDto() { DataTypeNodeId = dtd.Id, SortOrder = 0, Value = "test1" }); + DatabaseContext.Database.Insert(new DataTypePreValueDto() { DataTypeNodeId = dtd.Id, SortOrder = 1, Value = "test2" }); + + //this will cache the result + using (var repository = creator()) + { + var val = repository.GetPreValueAsString(Convert.ToInt32(id)); + } + + var cached = cache.RuntimeCache.GetCacheItemsByKeySearch(CacheKeys.DataTypePreValuesCacheKey + dtd.Id + "-"); + + Assert.IsNotNull(cached); + Assert.AreEqual(1, cached.Count()); + Assert.AreEqual(2, cached.Single().FormatAsDictionary().Count); + + using (var repository = creator()) + { + //ensure it still gets resolved! + var val = repository.GetPreValueAsString(Convert.ToInt32(id)); + Assert.AreEqual("test1", val); + } + } + [TearDown] public override void TearDown() { diff --git a/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs b/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs index f8c6de39cc..f91c08b455 100644 --- a/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs @@ -129,11 +129,15 @@ namespace Umbraco.Web.Cache payloads.ForEach(payload => { //clear both the Id and Unique Id cache since we cache both in the legacy classes :( - ApplicationContext.Current.ApplicationCache.ClearCacheByKeySearch( - string.Format("{0}{1}", CacheKeys.DataTypeCacheKey, payload.Id)); - ApplicationContext.Current.ApplicationCache.ClearCacheByKeySearch( + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch( + string.Format("{0}{1}", CacheKeys.DataTypeCacheKey, payload.Id)); + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch( string.Format("{0}{1}", CacheKeys.DataTypeCacheKey, payload.UniqueId)); + //clears the prevalue cache + ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch( + string.Format("{0}{1}", CacheKeys.DataTypePreValuesCacheKey, payload.Id)); + PublishedContentType.ClearDataType(payload.Id); });