diff --git a/src/Umbraco.Core/Persistence/NPocoSqlExtensions.cs b/src/Umbraco.Core/Persistence/NPocoSqlExtensions.cs
index 18027bcc1b..7aa8b707be 100644
--- a/src/Umbraco.Core/Persistence/NPocoSqlExtensions.cs
+++ b/src/Umbraco.Core/Persistence/NPocoSqlExtensions.cs
@@ -662,6 +662,26 @@ namespace Umbraco.Core.Persistence
return sql.Select(sql.GetColumns(columnExpressions: fields));
}
+ ///
+ /// Creates a SELECT DISTINCT Sql statement.
+ ///
+ /// The type of the DTO to select.
+ /// The origin sql.
+ /// Expressions indicating the columns to select.
+ /// The Sql statement.
+ ///
+ /// If is empty, all columns are selected.
+ ///
+ public static Sql SelectDistinct(this Sql sql, params Expression>[] fields)
+ {
+ if (sql == null) throw new ArgumentNullException(nameof(sql));
+ var columns = sql.GetColumns(columnExpressions: fields);
+ sql.Append("SELECT DISTINCT " + string.Join(", ", columns));
+ return sql;
+ }
+
+ //this.Append("SELECT " + string.Join(", ", columns), new object[0]);
+
///
/// Creates a SELECT Sql statement.
///
diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs
index 055ed7ae74..662254d1ee 100644
--- a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs
@@ -809,7 +809,7 @@ AND umbracoNode.id <> @id",
var targetLanguageIdS = targetLanguageId.HasValue ? targetLanguageId.ToString() : "NULL";
var sqlSelectTagsToInsert = Sql()
- .Select(x => x.Text, x => x.Group)
+ .SelectDistinct(x => x.Text, x => x.Group)
.Append(", " + targetLanguageIdS)
.From();
@@ -840,7 +840,7 @@ AND umbracoNode.id <> @id",
// and group, but for the target language
var sqlSelectRelationsToInsert = Sql()
- .Select(x => x.NodeId, x => x.PropertyTypeId)
+ .SelectDistinct(x => x.NodeId, x => x.PropertyTypeId)
.AndSelect("otag", x => x.Id)
.From()
.InnerJoin().On((rel, tag) => rel.TagId == tag.Id)
diff --git a/src/Umbraco.Tests/Services/ContentServiceTagsTests.cs b/src/Umbraco.Tests/Services/ContentServiceTagsTests.cs
index 196af5c0bd..8f66e98b76 100644
--- a/src/Umbraco.Tests/Services/ContentServiceTagsTests.cs
+++ b/src/Umbraco.Tests/Services/ContentServiceTagsTests.cs
@@ -256,6 +256,53 @@ namespace Umbraco.Tests.Services
Assert.IsFalse(enTagGroup.Any(x => x.Text == "plus"));
}
+ [Test]
+ public void TagsCanBecomeInvariant2()
+ {
+ var languageService = ServiceContext.LocalizationService;
+ languageService.Save(new Language("fr-FR")); // en-US is already there
+
+ var enId = ServiceContext.LocalizationService.GetLanguageIdByIsoCode("en-US").Value;
+
+ var contentService = ServiceContext.ContentService;
+ var contentTypeService = ServiceContext.ContentTypeService;
+ var tagService = ServiceContext.TagService;
+ var contentType = MockedContentTypes.CreateSimpleContentType("umbMandatory", "Mandatory Doc Type", true);
+ PropertyType propertyType;
+ contentType.PropertyGroups.First().PropertyTypes.Add(
+ propertyType = new PropertyType("test", ValueStorageType.Ntext, "tags")
+ {
+ DataTypeId = 1041,
+ Variations = ContentVariation.Culture
+ });
+ contentType.Variations = ContentVariation.Culture;
+ contentTypeService.Save(contentType);
+
+ IContent content1 = MockedContent.CreateSimpleContent(contentType, "Tagged content 1", -1);
+ content1.SetCultureName("name-fr", "fr-FR");
+ content1.SetCultureName("name-en", "en-US");
+ content1.AssignTags("tags", new[] { "hello", "world", "some", "tags", "plus" }, culture: "fr-FR");
+ content1.AssignTags("tags", new[] { "hello", "world", "another", "one" }, culture: "en-US");
+ contentService.SaveAndPublish(content1);
+
+ IContent content2 = MockedContent.CreateSimpleContent(contentType, "Tagged content 2", -1);
+ content2.SetCultureName("name-fr", "fr-FR");
+ content2.SetCultureName("name-en", "en-US");
+ content2.AssignTags("tags", new[] { "hello", "world", "some", "tags", "plus" }, culture: "fr-FR");
+ content2.AssignTags("tags", new[] { "hello", "world", "another", "one" }, culture: "en-US");
+ contentService.SaveAndPublish(content2);
+
+ //// pretend we already have invariant values
+ //using (var scope = ScopeProvider.CreateScope())
+ //{
+ // scope.Database.Execute("INSERT INTO [cmsTags] ([tag], [group], [languageId]) SELECT DISTINCT [tag], [group], NULL FROM [cmsTags] WHERE [languageId] IS NOT NULL");
+ //}
+
+ // this should work
+ propertyType.Variations = ContentVariation.Nothing;
+ Assert.DoesNotThrow(() => contentTypeService.Save(contentType));
+ }
+
[Test]
public void TagsCanBecomeInvariantByPropertyType()
{