Migrations: Ensure umbracoPropertyData column casing (#21015)

* Add migration to fix umbracoPropertyData column casing.

* Improve migration with column existence check and logging

- Add ILogger to log when column is renamed
- Check if column exists with incorrect casing before renaming
- Use fluent Rename API instead of raw SQL
- Add XML remarks documentation

?? Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Clarify what old and new column name really is

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: kjac <kja@umbraco.dk>
# Conflicts:
#	src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs
This commit is contained in:
Andy Butland
2025-12-01 19:01:55 +01:00
parent 1d59e20daa
commit 822a2fcf70
2 changed files with 57 additions and 0 deletions

View File

@@ -140,5 +140,8 @@ public class UmbracoPlan : MigrationPlan
To<V_17_0_0.AddLastSyncedTable>("26179D88-58CE-4C92-B4A4-3CBA6E7188AC");
To<V_17_0_0.EnsureDefaultMediaFolderHasDefaultCollection>("{8B2C830A-4FFB-4433-8337-8649B0BF52C8}");
To<V_17_0_0.InvalidateBackofficeUserAccess>("{1C38D589-26BB-4A46-9ABE-E4A0DF548A87}");
// To 17.0.1
To<V_17_0_1.EnsureUmbracoPropertyDataColumnCasing>("{BE5CA411-E12D-4455-A59E-F12A669E5363}");
}
}

View File

@@ -0,0 +1,54 @@
using Microsoft.Extensions.Logging;
using NPoco;
using static Umbraco.Cms.Core.Constants;
using ColumnInfo = Umbraco.Cms.Infrastructure.Persistence.SqlSyntax.ColumnInfo;
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_17_0_1;
/// <summary>
/// Ensures the propertyTypeId column in umbracoPropertyData has correct camel case naming.
/// </summary>
/// <remarks>
/// SQL Server is case sensitive for columns used in a SQL Bulk insert statement (which is used in publishing
/// operations on umbracoPropertyData).
/// Earlier versions of Umbraco used all lower case for the propertyTypeId column name (propertytypeid), whereas newer versions
/// use camel case (propertyTypeId).
/// </remarks>
public class EnsureUmbracoPropertyDataColumnCasing : AsyncMigrationBase
{
private readonly ILogger<EnsureUmbracoPropertyDataColumnCasing> _logger;
/// <summary>
/// Initializes a new instance of the <see cref="EnsureUmbracoPropertyDataColumnCasing"/> class.
/// </summary>
public EnsureUmbracoPropertyDataColumnCasing(IMigrationContext context, ILogger<EnsureUmbracoPropertyDataColumnCasing> logger)
: base(context) => _logger = logger;
/// <inheritdoc/>
protected override Task MigrateAsync()
{
// We only need to do this for SQL Server.
if (DatabaseType == DatabaseType.SQLite)
{
return Task.CompletedTask;
}
const string oldColumnName = "propertytypeid";
const string newColumnName = "propertyTypeId";
ColumnInfo[] columns = [.. SqlSyntax.GetColumnsInSchema(Context.Database)];
ColumnInfo? targetColumn = columns
.FirstOrDefault(x => x.TableName == DatabaseSchema.Tables.PropertyData && string.Equals(x.ColumnName, oldColumnName, StringComparison.InvariantCulture));
if (targetColumn is not null)
{
// The column exists with incorrect casing, we need to rename it.
Rename.Column(oldColumnName)
.OnTable(DatabaseSchema.Tables.PropertyData)
.To(newColumnName)
.Do();
_logger.LogInformation("Renamed column {OldColumnName} to {NewColumnName} on table {TableName}", oldColumnName, newColumnName, DatabaseSchema.Tables.PropertyData);
}
return Task.CompletedTask;
}
}