diff --git a/src/Umbraco.Core/Models/PropertyType.cs b/src/Umbraco.Core/Models/PropertyType.cs index 1e950a876c..34775ccf89 100644 --- a/src/Umbraco.Core/Models/PropertyType.cs +++ b/src/Umbraco.Core/Models/PropertyType.cs @@ -21,6 +21,7 @@ namespace Umbraco.Core.Models private string _alias; private string _description; private int _dataTypeId; + private Guid _dataTypeKey; private Lazy _propertyGroupId; private string _propertyEditorAlias; private ValueStorageType _valueStorageType; @@ -139,6 +140,13 @@ namespace Umbraco.Core.Models set => SetPropertyValueAndDetectChanges(value, ref _dataTypeId, nameof(DataTypeId)); } + [DataMember] + public Guid DataTypeKey + { + get => _dataTypeKey; + set => SetPropertyValueAndDetectChanges(value, ref _dataTypeKey, nameof(DataTypeKey)); + } + /// /// Gets or sets the alias of the property editor for this property type. /// diff --git a/src/Umbraco.Core/Persistence/Factories/PropertyGroupFactory.cs b/src/Umbraco.Core/Persistence/Factories/PropertyGroupFactory.cs index c134748047..db8e2b20d9 100644 --- a/src/Umbraco.Core/Persistence/Factories/PropertyGroupFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/PropertyGroupFactory.cs @@ -54,6 +54,7 @@ namespace Umbraco.Core.Persistence.Factories propertyType.Alias = typeDto.Alias; propertyType.DataTypeId = typeDto.DataTypeId; + propertyType.DataTypeKey = typeDto.DataTypeDto.NodeDto.UniqueId; propertyType.Description = typeDto.Description; propertyType.Id = typeDto.Id; propertyType.Key = typeDto.UniqueId; diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeCommonRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeCommonRepository.cs index ccafb9f771..5ecd041bc5 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeCommonRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeCommonRepository.cs @@ -7,6 +7,7 @@ using Umbraco.Core.Models; using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Scoping; +using static Umbraco.Core.Persistence.NPocoSqlExtensions.Statics; namespace Umbraco.Core.Persistence.Repositories.Implement { @@ -189,9 +190,30 @@ namespace Umbraco.Core.Persistence.Repositories.Implement var sql2 = Sql() .Select(r => r.Select(x => x.DataTypeDto)) + + //TODO: Why doesn't this overload have the ability to auto alias columns like the inner select above, instead we need to manually apply all aliases + //QUESTION: Why doesn't this work? but the below `.AndSelect()` works? The problem now is that the output SQL has duplicate column names. + // NPoco seems to be able to map this correctly but it would be better to have aliased columns like below. These alias names seem to follow some sort + // of convention with the double underscore and these columns are in the exact same order as the auto-produced ones, however NPoco does not map these + // columns? + //.AndSelect( + // x => Alias(x.NodeId, "NodeDto__NodeId"), + // x => Alias(x.UniqueId, "NodeDto__UniqueId"), + // x => Alias(x.ParentId, "NodeDto__ParentId"), + // x => Alias(x.Level, "NodeDto__Level"), + // x => Alias(x.Path, "NodeDto__Path"), + // x => Alias(x.SortOrder, "NodeDto__SortOrder"), + // x => Alias(x.Trashed, "NodeDto__Trashed"), + // x => Alias(x.UserId, "NodeDto__UserId"), + // x => Alias(x.Text, "NodeDto__Text"), + // x => Alias(x.NodeObjectType, "NodeDto__NodeObjectType"), + // x => Alias(x.CreateDate, "NodeDto__CreateDate")) + .AndSelect() + .AndSelect() .From() .InnerJoin().On((pt, dt) => pt.DataTypeId == dt.NodeId) + .InnerJoin().On((dt, n) => dt.NodeId == n.NodeId) .InnerJoin().On((pt, ct) => pt.ContentTypeId == ct.NodeId) .LeftJoin().On((pt, ptg) => pt.PropertyTypeGroupId == ptg.Id) .LeftJoin().On((pt, mpt) => pt.Id == mpt.PropertyTypeId) @@ -290,6 +312,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { Description = dto.Description, DataTypeId = dto.DataTypeId, + DataTypeKey = dto.DataTypeDto.NodeDto.UniqueId, Id = dto.Id, Key = dto.UniqueId, Mandatory = dto.Mandatory, diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs index 591fa2b660..22c9244d8f 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs @@ -1013,8 +1013,9 @@ AND umbracoNode.id <> @id", if (propertyType.PropertyEditorAlias.IsNullOrWhiteSpace() == false) { var sql = Sql() - .SelectAll() + .Select(dt => dt.Select(x => x.NodeDto)) .From() + .InnerJoin().On((dt, n) => dt.NodeId == n.NodeId) .Where("propertyEditorAlias = @propertyEditorAlias", new { propertyEditorAlias = propertyType.PropertyEditorAlias }) .OrderBy(typeDto => typeDto.NodeId); var datatype = Database.FirstOrDefault(sql); @@ -1022,6 +1023,7 @@ AND umbracoNode.id <> @id", if (datatype != null) { propertyType.DataTypeId = datatype.NodeId; + propertyType.DataTypeKey = datatype.NodeDto.UniqueId; } else { diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberTypeRepository.cs index 61981a42e3..d96854743e 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberTypeRepository.cs @@ -225,6 +225,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { //this reset's its current data type reference which will be re-assigned based on the property editor assigned on the next line propertyType.DataTypeId = 0; + propertyType.DataTypeKey = default; } } } diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentPropertyBasic.cs b/src/Umbraco.Web/Models/ContentEditing/ContentPropertyBasic.cs index 7d6d066e35..f0f5bba7c4 100644 --- a/src/Umbraco.Web/Models/ContentEditing/ContentPropertyBasic.cs +++ b/src/Umbraco.Web/Models/ContentEditing/ContentPropertyBasic.cs @@ -22,8 +22,10 @@ namespace Umbraco.Web.Models.ContentEditing [Required] public int Id { get; set; } - [DataMember(Name = "dataTypeId", IsRequired = false)] - public Guid? DataTypeId { get; set; } + //fixme: This name dataTypeId is inconsistent, but requires us to change it everywhere in angular + [DataMember(Name = "dataTypeId", IsRequired = false)] + [ReadOnly(true)] + public Guid DataTypeKey { get; set; } [DataMember(Name = "value")] public object Value { get; set; } diff --git a/src/Umbraco.Web/Models/ContentEditing/PropertyTypeBasic.cs b/src/Umbraco.Web/Models/ContentEditing/PropertyTypeBasic.cs index cde9d0dabc..d180a68a2c 100644 --- a/src/Umbraco.Web/Models/ContentEditing/PropertyTypeBasic.cs +++ b/src/Umbraco.Web/Models/ContentEditing/PropertyTypeBasic.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; @@ -43,6 +44,10 @@ namespace Umbraco.Web.Models.ContentEditing [Required] public int DataTypeId { get; set; } + [DataMember(Name = "dataTypeKey")] + [ReadOnly(true)] + public Guid DataTypeKey { get; set; } + //SD: Is this really needed ? [DataMember(Name = "groupId")] public int GroupId { get; set; } diff --git a/src/Umbraco.Web/Models/Mapping/ContentPropertyBasicMapper.cs b/src/Umbraco.Web/Models/Mapping/ContentPropertyBasicMapper.cs index 57a06c2175..36c1b360b2 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentPropertyBasicMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentPropertyBasicMapper.cs @@ -50,13 +50,7 @@ namespace Umbraco.Web.Models.Mapping dest.Alias = property.Alias; dest.PropertyEditor = editor; dest.Editor = editor.Alias; - - //fixme: although this might get cached, if a content item has 100 properties of different data types, then this means this is going to be 100 extra DB queries :( :( :( - // - ideally, we'd just have the DataTypeKey alongside the DataTypeId which is loaded in the single sql statement which should be relatively easy. - var dataTypeKey = _entityService.GetKey(property.PropertyType.DataTypeId, UmbracoObjectTypes.DataType); - if (!dataTypeKey.Success) - throw new InvalidOperationException("Can't get the unique key from the id: " + property.PropertyType.DataTypeId); - dest.DataTypeId = dataTypeKey.Result; + dest.DataTypeKey = property.PropertyType.DataTypeKey; // if there's a set of property aliases specified, we will check if the current property's value should be mapped. // if it isn't one of the ones specified in 'includeProperties', we will just return the result without mapping the Value. diff --git a/src/Umbraco.Web/Models/Mapping/ContentTypeMapDefinition.cs b/src/Umbraco.Web/Models/Mapping/ContentTypeMapDefinition.cs index a438f04781..fc029eabe4 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentTypeMapDefinition.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentTypeMapDefinition.cs @@ -219,6 +219,7 @@ namespace Umbraco.Web.Models.Mapping { target.Name = source.Label; target.DataTypeId = source.DataTypeId; + target.DataTypeKey = source.DataTypeKey; target.Mandatory = source.Validation.Mandatory; target.ValidationRegExp = source.Validation.Pattern; target.Variations = source.AllowCultureVariant ? ContentVariation.Culture : ContentVariation.Nothing; @@ -334,6 +335,7 @@ namespace Umbraco.Web.Models.Mapping target.Alias = source.Alias; target.AllowCultureVariant = source.AllowCultureVariant; target.DataTypeId = source.DataTypeId; + target.DataTypeKey = source.DataTypeKey; target.Description = source.Description; target.GroupId = source.GroupId; target.Id = source.Id; @@ -349,6 +351,7 @@ namespace Umbraco.Web.Models.Mapping target.Alias = source.Alias; target.AllowCultureVariant = source.AllowCultureVariant; target.DataTypeId = source.DataTypeId; + target.DataTypeKey = source.DataTypeKey; target.Description = source.Description; target.GroupId = source.GroupId; target.Id = source.Id; diff --git a/src/Umbraco.Web/Models/Mapping/PropertyTypeGroupMapper.cs b/src/Umbraco.Web/Models/Mapping/PropertyTypeGroupMapper.cs index 8c5f347799..a184ac92cf 100644 --- a/src/Umbraco.Web/Models/Mapping/PropertyTypeGroupMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/PropertyTypeGroupMapper.cs @@ -231,6 +231,7 @@ namespace Umbraco.Web.Models.Mapping GroupId = groupId, Inherited = inherited, DataTypeId = p.DataTypeId, + DataTypeKey = p.DataTypeKey, SortOrder = p.SortOrder, ContentTypeId = contentType.Id, ContentTypeName = contentType.Name,