diff --git a/src/umbraco.cms/businesslogic/ContentType.cs b/src/umbraco.cms/businesslogic/ContentType.cs
index 073324fa96..9634047464 100644
--- a/src/umbraco.cms/businesslogic/ContentType.cs
+++ b/src/umbraco.cms/businesslogic/ContentType.cs
@@ -4,13 +4,13 @@ using System.Collections.Generic;
using System.Threading;
using System.Runtime.CompilerServices;
using System.Linq;
-using umbraco.cms.businesslogic.cache;
-using umbraco.cms.businesslogic.datatype;
-using umbraco.cms.businesslogic.language;
-using umbraco.cms.businesslogic.propertytype;
+using Umbraco.Core;
+using Umbraco.Core.Logging;
using umbraco.cms.businesslogic.web;
using umbraco.DataLayer;
-using umbraco.BusinessLogic;
+using DataTypeDefinition = umbraco.cms.businesslogic.datatype.DataTypeDefinition;
+using Language = umbraco.cms.businesslogic.language.Language;
+using PropertyType = umbraco.cms.businesslogic.propertytype.PropertyType;
namespace umbraco.cms.businesslogic
{
@@ -44,24 +44,6 @@ namespace umbraco.cms.businesslogic
public ContentType(Guid id, bool noSetup) : base(id, noSetup) { }
- /////
- ///// Initializes a new instance of the class.
- /////
- ///// The id.
- ///// if set to true [use optimized mode] which loads in the data from the
- ///// database in an optimized manner (less queries)
- /////
- //public ContentType(bool optimizedMode, int id)
- // : base(id, optimizedMode)
- //{
- // this._optimizedMode = optimizedMode;
-
- // if (optimizedMode)
- // {
-
- // }
- //}
-
///
/// Creates a new content type object manually.
///
@@ -82,7 +64,7 @@ namespace umbraco.cms.businesslogic
_iconurl = icon;
_thumbnail = thumbnail;
if (masterContentType.HasValue)
- m_masterContentType = masterContentType.Value;
+ _masterContentType = masterContentType.Value;
}
#endregion
@@ -95,8 +77,6 @@ namespace umbraco.cms.businesslogic
FROM umbracoNode INNER JOIN cmsContentType ON umbracoNode.id = cmsContentType.nodeId
WHERE nodeObjectType = @nodeObjectType";
- private static readonly object m_Locker = new object();
-
#endregion
#region Static Methods
@@ -105,8 +85,7 @@ namespace umbraco.cms.businesslogic
/// Used for cache so we don't have to lookup column names all the time, this is actually only used for the ChildrenAsTable methods
///
private static readonly ConcurrentDictionary> AliasToNames = new ConcurrentDictionary>();
-
- private static Dictionary, Guid> _propertyTypeCache = new Dictionary, Guid>();
+ private static readonly ConcurrentDictionary, Guid> PropertyTypeCache = new ConcurrentDictionary, Guid>();
///
/// Returns a content type's columns alias -> name mapping
@@ -118,121 +97,108 @@ namespace umbraco.cms.businesslogic
///
internal static IDictionary GetAliasesAndNames(string contentTypeAlias)
{
- IDictionary cached;
- if (AliasToNames.TryGetValue(contentTypeAlias, out cached))
- {
- return cached;
- }
-
- var ct = ContentType.GetByAlias(contentTypeAlias);
- var userFields = ct.PropertyTypes.ToDictionary(x => x.Alias, x => x.Name);
- AliasToNames.TryAdd(contentTypeAlias, userFields);
- return userFields;
+ return AliasToNames.GetOrAdd(contentTypeAlias, s =>
+ {
+ var ct = GetByAlias(contentTypeAlias);
+ var userFields = ct.PropertyTypes.ToDictionary(x => x.Alias, x => x.Name);
+ return userFields;
+ });
}
-
- public static void RemoveFromDataTypeCache(string contentTypeAlias)
+
+ ///
+ /// Removes the static object cache
+ ///
+ ///
+ public static void RemoveFromDataTypeCache(string contentTypeAlias)
{
- lock (_propertyTypeCache)
+ var toDelete = PropertyTypeCache.Keys.Where(key => string.Equals(key.Item1, contentTypeAlias)).ToList();
+ foreach (var key in toDelete)
{
- List> toDelete = new List>();
- foreach (Tuple key in _propertyTypeCache.Keys)
- {
- if (string.Equals(key.first, contentTypeAlias))
- {
- toDelete.Add(key);
- }
- }
- foreach (Tuple key in toDelete)
- {
- if(_propertyTypeCache != null)
- _propertyTypeCache.Remove(key);
- }
+ Guid id;
+ PropertyTypeCache.TryRemove(key, out id);
}
- //don't put lock around this as it is ConcurrentDictionary.
- AliasToNames.Clear();
+ AliasToNames.Clear();
}
+
+ ///
+ /// Removes the static object cache
+ ///
+ internal static void RemoveAllDataTypeCache()
+ {
+ AliasToNames.Clear();
+ PropertyTypeCache.Clear();
+ }
+
public static Guid GetDataType(string contentTypeAlias, string propertyTypeAlias)
{
- Tuple key = new Tuple()
- {
- first = contentTypeAlias,
- second = propertyTypeAlias
- };
- //The property type is not on IProperty (it's not stored in NodeFactory)
- //first check the cache
- if (_propertyTypeCache != null && _propertyTypeCache.ContainsKey(key))
- {
- return _propertyTypeCache[key];
- }
+ var key = new System.Tuple(contentTypeAlias, propertyTypeAlias);
- //Instead of going via API, run this query to find the control type
- //by-passes a lot of queries just to determine if this is a true/false data type
-
- //This SQL returns a larger recordset than intended
- //causing controlId to sometimes be null instead of correct
- //because all properties for the type are returned
- //side effect of changing inner join to left join when adding masterContentType
- //string sql = "select " +
- // "cmsDataType.controlId, masterContentType.alias as masterAlias " +
- // "from " +
- // "cmsContentType " +
- // "inner join cmsPropertyType on (cmsContentType.nodeId = cmsPropertyType.contentTypeId) " +
- // "left join cmsDataType on (cmsPropertyType.dataTypeId = cmsDataType.nodeId) and cmsPropertyType.Alias = @propertyAlias " +
- // "left join cmsContentType masterContentType on masterContentType.nodeid = cmsContentType.masterContentType " +
- // "where cmsContentType.alias = @contentTypeAlias";
-
- //this SQL correctly returns a single row when the property exists, but still returns masterAlias if it doesn't
- string sql = "select cmsDataType.controlId, masterContentType.alias as masterAlias " +
- "from " +
- "cmsContentType " +
- "left join cmsPropertyType on (cmsContentType.nodeId = cmsPropertyType.contentTypeId and cmsPropertyType.Alias = @propertyAlias) " +
- "left join cmsDataType on (cmsPropertyType.dataTypeId = cmsDataType.nodeId) " +
- "left join cmsContentType masterContentType on masterContentType.nodeid = cmsContentType.masterContentType " +
- "where " +
- "cmsContentType.alias = @contentTypeAlias";
-
- //Ensure that getdatatype doesn't throw an exception
- //http://our.umbraco.org/forum/developers/razor/18085-Access-custom-node-properties-with-Razor
-
- //grab the controlid or test for parent
- Guid controlId = Guid.Empty;
- IRecordsReader reader = null;
+ //NOTE: We only have a try/catch here for legacy reasons, I don't see any reason to have it
+ // but it was here before so we'll need to keep it for this legacy version.
+ // If an error occurs, we return an empty GUID but do not cache this.
try
{
- reader = Application.SqlHelper.ExecuteReader(sql,
- Application.SqlHelper.CreateParameter("@contentTypeAlias", contentTypeAlias),
- Application.SqlHelper.CreateParameter("@propertyAlias", propertyTypeAlias)
- );
- if (reader.Read())
- {
- if (!reader.IsNull("controlId"))
- controlId = reader.GetGuid("controlId");
- else if (!reader.IsNull("masterAlias") && !String.IsNullOrEmpty(reader.GetString("masterAlias")))
- {
- controlId = GetDataType(reader.GetString("masterAlias"), propertyTypeAlias);
- }
+ return PropertyTypeCache.GetOrAdd(
+ key,
+ tuple =>
+ {
+ //Instead of going via API, run this query to find the control type
+ //by-passes a lot of queries just to determine if this is a true/false data type
- }
- }
- catch (UmbracoException)
- {
- _propertyTypeCache.Add(key, controlId);
- }
- finally
- {
- if (reader != null)
- {
- reader.Close();
- }
- }
+ //This SQL returns a larger recordset than intended
+ //causing controlId to sometimes be null instead of correct
+ //because all properties for the type are returned
+ //side effect of changing inner join to left join when adding masterContentType
+ //string sql = "select " +
+ // "cmsDataType.controlId, masterContentType.alias as masterAlias " +
+ // "from " +
+ // "cmsContentType " +
+ // "inner join cmsPropertyType on (cmsContentType.nodeId = cmsPropertyType.contentTypeId) " +
+ // "left join cmsDataType on (cmsPropertyType.dataTypeId = cmsDataType.nodeId) and cmsPropertyType.Alias = @propertyAlias " +
+ // "left join cmsContentType masterContentType on masterContentType.nodeid = cmsContentType.masterContentType " +
+ // "where cmsContentType.alias = @contentTypeAlias";
- //add to cache
- if (!_propertyTypeCache.ContainsKey(key))
- {
- _propertyTypeCache.Add(key, controlId);
- }
- return controlId;
+ //this SQL correctly returns a single row when the property exists, but still returns masterAlias if it doesn't
+ var sql = "select cmsDataType.controlId, masterContentType.alias as masterAlias " +
+ "from " +
+ "cmsContentType " +
+ "left join cmsPropertyType on (cmsContentType.nodeId = cmsPropertyType.contentTypeId and cmsPropertyType.Alias = @propertyAlias) " +
+ "left join cmsDataType on (cmsPropertyType.dataTypeId = cmsDataType.nodeId) " +
+ "left join cmsContentType masterContentType on masterContentType.nodeid = cmsContentType.masterContentType " +
+ "where " +
+ "cmsContentType.alias = @contentTypeAlias";
+ //Ensure that getdatatype doesn't throw an exception
+ //http://our.umbraco.org/forum/developers/razor/18085-Access-custom-node-properties-with-Razor
+
+ //grab the controlid or test for parent
+ var controlId = Guid.Empty;
+ using (var reader = SqlHelper.ExecuteReader(
+ sql,
+ SqlHelper.CreateParameter("@contentTypeAlias", contentTypeAlias),
+ SqlHelper.CreateParameter("@propertyAlias", propertyTypeAlias)
+ ))
+ {
+ if (reader.Read())
+ {
+ if (!reader.IsNull("controlId"))
+ {
+ controlId = reader.GetGuid("controlId");
+ }
+ else if (!reader.IsNull("masterAlias") && !String.IsNullOrEmpty(reader.GetString("masterAlias")))
+ {
+ controlId = GetDataType(reader.GetString("masterAlias"), propertyTypeAlias);
+ }
+ }
+ }
+ return controlId;
+ });
+ }
+ catch (Exception ex)
+ {
+ LogHelper.Error("An error occurred in GetDataType", ex);
+ return Guid.Empty;
+ }
}
@@ -243,32 +209,10 @@ namespace umbraco.cms.businesslogic
///
public static ContentType GetContentType(int id)
{
- return Cache.GetCacheItem(string.Format("UmbracoContentType{0}", id.ToString()),
- m_Locker,
- TimeSpan.FromMinutes(30),
- delegate
- {
- return new ContentType(id);
- });
- }
-
- ///
- /// If true, this instance uses default umbraco data only.
- ///
- /// The ct.
- ///
- private static bool usesUmbracoDataOnly(ContentType ct)
- {
- bool retVal = true;
- foreach (PropertyType pt in ct.PropertyTypes)
- {
- if (!DataTypeDefinition.IsDefaultData(pt.DataTypeDefinition.DataType.Data))
- {
- retVal = false;
- break;
- }
- }
- return retVal;
+ return ApplicationContext.Current.ApplicationCache.GetCacheItem
+ (string.Format("UmbracoContentType{0}", id),
+ TimeSpan.FromMinutes(30),
+ () => new ContentType(id));
}
// This is needed, because the Tab class is protected and as such it's not possible for
@@ -315,29 +259,25 @@ namespace umbraco.cms.businesslogic
/// The Id of the Tab on which the PropertyType is placed
public static int getTabIdFromPropertyType(PropertyType pt)
{
- object tmp = SqlHelper.ExecuteScalar