diff --git a/src/Umbraco.Infrastructure/Migrations/Upgrade/V_9_0_0/DictionaryTablesIndexes.cs b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_9_0_0/DictionaryTablesIndexes.cs index b8f657c6bd..b050f90d82 100644 --- a/src/Umbraco.Infrastructure/Migrations/Upgrade/V_9_0_0/DictionaryTablesIndexes.cs +++ b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_9_0_0/DictionaryTablesIndexes.cs @@ -22,19 +22,29 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_0_0 { var indexDictionaryDto = $"IX_{DictionaryDto.TableName}_{IndexedDictionaryColumn}"; var indexLanguageTextDto = $"IX_{LanguageTextDto.TableName}_{IndexedLanguageTextColumn}"; + var dictionaryColumnsToBeIndexed = new[] { IndexedDictionaryColumn }; + var langTextColumnsToBeIndexed = new[] { IndexedLanguageTextColumn, "UniqueId" }; - // Delete existing - DeleteIndex(indexDictionaryDto); - // Re-create/Add - AddUniqueConstraint(new[] { IndexedDictionaryColumn }, indexDictionaryDto); + var dictionaryTableHasDuplicates = ContainsDuplicates(dictionaryColumnsToBeIndexed); + var langTextTableHasDuplicates = ContainsDuplicates(langTextColumnsToBeIndexed); - // Delete existing - DeleteIndex(indexLanguageTextDto); + // Check if there are any duplicates before we delete and re-create the indexes since + // if there are duplicates we won't be able to create the new unique indexes + if (!dictionaryTableHasDuplicates) + { + // Delete existing + DeleteIndex(indexDictionaryDto); + } - var langTextcolumns = new[] { IndexedLanguageTextColumn, "UniqueId" }; + if (!langTextTableHasDuplicates) + { + // Delete existing + DeleteIndex(indexLanguageTextDto); + } - // Re-create/Add - AddUniqueConstraint(langTextcolumns, indexLanguageTextDto); + // Try to re-create/add + TryAddUniqueConstraint(dictionaryColumnsToBeIndexed, indexDictionaryDto, dictionaryTableHasDuplicates); + TryAddUniqueConstraint(langTextColumnsToBeIndexed, indexLanguageTextDto, langTextTableHasDuplicates); } private void DeleteIndex(string indexName) @@ -56,7 +66,7 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_0_0 new ExecuteSqlStatementExpression(Context) { SqlStatement = Context.SqlContext.SqlSyntax.Format(index) }.Execute(); } - private void AddUniqueConstraint(string[] columns, string index) + private void TryAddUniqueConstraint(string[] columns, string index, bool containsDuplicates) { var tableDef = DefinitionFactory.GetTableDefinition(typeof(TDto), Context.SqlContext.SqlSyntax); @@ -64,7 +74,7 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_0_0 // This seems to be better than relying on catching an exception as this leads to // transaction errors: "This SqlTransaction has completed; it is no longer usable". var columnsDescription = string.Join("], [", columns); - if (ContainsDuplicates(columns)) + if (containsDuplicates) { var message = $"Could not create unique constraint on [{tableDef.Name}] due to existing " + $"duplicate records across the column{(columns.Length > 1 ? "s" : string.Empty)}: [{columnsDescription}]."; @@ -126,8 +136,7 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_0_0 return Database.ExecuteScalar(distinctCountQuery); } - private void LogIncompleteMigrationStep(string message) => - Logger.LogError($"Database migration step failed: {message}"); + private void LogIncompleteMigrationStep(string message) => Logger.LogError($"Database migration step failed: {message}"); private string StringConvertedAndQuotedColumnName(string column) => $"CONVERT(nvarchar(1000),{QuoteColumnName(column)})";