diff --git a/src/Umbraco.Core/EnumerableExtensions.cs b/src/Umbraco.Core/EnumerableExtensions.cs index 177e82bbf1..e8565f3bc7 100644 --- a/src/Umbraco.Core/EnumerableExtensions.cs +++ b/src/Umbraco.Core/EnumerableExtensions.cs @@ -295,22 +295,5 @@ namespace Umbraco.Core return list1Groups.Count == list2Groups.Count && list1Groups.All(g => g.Count() == list2Groups[g.Key].Count()); } - - /// - /// Returns the items of the given enumerable as a pure enumerable. - /// - /// When quering lists using methods such as , the result, despite appearing to look like and quack like an - /// the type is actually an instance of - /// - /// - ///The item to find. - ///The index of the first matching item, or -1 if the item was not found. - internal static IEnumerable Yield(this IEnumerable source) - { - foreach (var element in source) - { - yield return element; - } - } } } diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/SliderValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/SliderValueConverter.cs index f3354eb631..93cdd95cab 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/SliderValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/SliderValueConverter.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Linq; using Umbraco.Core.Configuration; using Umbraco.Core.Models; @@ -88,13 +89,26 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters /// private bool IsRangeDataType(int dataTypeId) { - // ** This must be cached (U4-8862) ** - var enableRange = - _dataTypeService.GetPreValuesCollectionByDataTypeId(dataTypeId) - .PreValuesAsDictionary.FirstOrDefault( - x => string.Equals(x.Key, "enableRange", StringComparison.InvariantCultureIgnoreCase)).Value; + // GetPreValuesCollectionByDataTypeId is cached at repository level; + // still, the collection is deep-cloned so this is kinda expensive, + // better to cache here + trigger refresh in DataTypeCacheRefresher - return enableRange != null && enableRange.Value.TryConvertTo().Result; + return Storages.GetOrAdd(dataTypeId, id => + { + var preValue = _dataTypeService.GetPreValuesCollectionByDataTypeId(id) + .PreValuesAsDictionary + .FirstOrDefault(x => string.Equals(x.Key, "enableRange", StringComparison.InvariantCultureIgnoreCase)) + .Value; + + return preValue != null && preValue.Value.TryConvertTo().Result; + }); + } + + private static readonly ConcurrentDictionary Storages = new ConcurrentDictionary(); + + internal static void ClearCaches() + { + Storages.Clear(); } } } diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/TagsValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/TagsValueConverter.cs index 8b53492515..b085748487 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/TagsValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/TagsValueConverter.cs @@ -1,9 +1,12 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Umbraco.Core.Configuration; +using Umbraco.Core.Events; +using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; @@ -74,18 +77,26 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters /// private bool JsonStorageType(int dataTypeId) { - // ** This must be cached (U4-8862) ** - var storageType = - _dataTypeService.GetPreValuesCollectionByDataTypeId(dataTypeId) - .PreValuesAsDictionary.FirstOrDefault( - x => string.Equals(x.Key, "storageType", StringComparison.InvariantCultureIgnoreCase)).Value; + // GetPreValuesCollectionByDataTypeId is cached at repository level; + // still, the collection is deep-cloned so this is kinda expensive, + // better to cache here + trigger refresh in DataTypeCacheRefresher - if (storageType != null && storageType.Value.InvariantEquals("Json")) + return Storages.GetOrAdd(dataTypeId, id => { - return true; - } + var preValue = _dataTypeService.GetPreValuesCollectionByDataTypeId(id) + .PreValuesAsDictionary + .FirstOrDefault(x => string.Equals(x.Key, "storageType", StringComparison.InvariantCultureIgnoreCase)) + .Value; - return false; + return preValue != null && preValue.Value.InvariantEquals("json"); + }); + } + + private static readonly ConcurrentDictionary Storages = new ConcurrentDictionary(); + + internal static void ClearCaches() + { + Storages.Clear(); } } } diff --git a/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs b/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs index 11b3ab6294..fe629a6ccf 100644 --- a/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs @@ -5,6 +5,8 @@ using Umbraco.Core.Cache; using System.Linq; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.PropertyEditors.ValueConverters; +using Umbraco.Web.PropertyEditors.ValueConverters; namespace Umbraco.Web.Cache @@ -111,6 +113,10 @@ namespace Umbraco.Web.Cache PublishedContentType.ClearDataType(payload.Id); }); + TagsValueConverter.ClearCaches(); + MultipleMediaPickerPropertyConverter.ClearCaches(); + SliderValueConverter.ClearCaches(); + base.Refresh(jsonPayload); } } diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/MultiNodeTreePickerPropertyConverter.cs b/src/Umbraco.Web/PropertyEditors/ValueConverters/MultiNodeTreePickerPropertyConverter.cs index e421cb03a6..c0c0321e91 100644 --- a/src/Umbraco.Web/PropertyEditors/ValueConverters/MultiNodeTreePickerPropertyConverter.cs +++ b/src/Umbraco.Web/PropertyEditors/ValueConverters/MultiNodeTreePickerPropertyConverter.cs @@ -132,7 +132,6 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters if (nodeIds.Length > 0) { var umbHelper = new UmbracoHelper(UmbracoContext.Current); - var objectType = UmbracoObjectTypes.Unknown; foreach (var nodeId in nodeIds) @@ -148,8 +147,8 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters } } } - //TODO: Get rid of this Yield thing - return multiNodeTreePicker.Yield().Where(x => x != null); + + return multiNodeTreePicker; } // return the first nodeId as this is one of the excluded properties that expects a single id @@ -170,11 +169,13 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters { var item = udi.ToPublishedContent(); if (item != null) + { multiNodeTreePicker.Add(item); + } } } - //TODO: Get rid of this Yield thing - return multiNodeTreePicker.Yield().Where(x => x != null); + + return multiNodeTreePicker; } // return the first nodeId as this is one of the excluded properties that expects a single id diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/MultipleMediaPickerPropertyConverter.cs b/src/Umbraco.Web/PropertyEditors/ValueConverters/MultipleMediaPickerPropertyConverter.cs index 72d746d779..ddb50a0e31 100644 --- a/src/Umbraco.Web/PropertyEditors/ValueConverters/MultipleMediaPickerPropertyConverter.cs +++ b/src/Umbraco.Web/PropertyEditors/ValueConverters/MultipleMediaPickerPropertyConverter.cs @@ -8,6 +8,7 @@ // -------------------------------------------------------------------------------------------------------------------- using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; @@ -223,13 +224,26 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters /// public bool IsMultipleDataType(int dataTypeId) { - // ** This must be cached (U4-8862) ** - var multiPickerPreValue = - _dataTypeService.GetPreValuesCollectionByDataTypeId(dataTypeId) - .PreValuesAsDictionary.FirstOrDefault( - x => string.Equals(x.Key, "multiPicker", StringComparison.InvariantCultureIgnoreCase)).Value; + // GetPreValuesCollectionByDataTypeId is cached at repository level; + // still, the collection is deep-cloned so this is kinda expensive, + // better to cache here + trigger refresh in DataTypeCacheRefresher - return multiPickerPreValue != null && multiPickerPreValue.Value.TryConvertTo().Result; + return Storages.GetOrAdd(dataTypeId, id => + { + var preValue = _dataTypeService.GetPreValuesCollectionByDataTypeId(id) + .PreValuesAsDictionary + .FirstOrDefault(x => string.Equals(x.Key, "multiPicker", StringComparison.InvariantCultureIgnoreCase)) + .Value; + + return preValue != null && preValue.Value.TryConvertTo().Result; + }); + } + + private static readonly ConcurrentDictionary Storages = new ConcurrentDictionary(); + + internal static void ClearCaches() + { + Storages.Clear(); } } } \ No newline at end of file