Support persistence of unrestricted selections from the check box list (#19856)

* Use unrestricted text field when creating data types based on the CheckboxList property editor.
Initialize default checkbox list data type with the unrestricted text field for storage on new installs.
Migrate existing data type and property data.

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Correctly use constant.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Andy Butland
2025-08-05 13:19:25 +02:00
committed by GitHub
parent 73d2f207d0
commit 5fc12ec36e
6 changed files with 57 additions and 5 deletions

View File

@@ -14,13 +14,13 @@ public enum ValueStorageType
// changing the casing of values.
/// <summary>
/// Store property value as NText.
/// Store property value as NVarchar(max).
/// </summary>
[EnumMember]
Ntext,
/// <summary>
/// Store property value as NVarChar.
/// Store property value as NVarChar(512).
/// </summary>
[EnumMember]
Nvarchar,

View File

@@ -45,7 +45,7 @@ public static class ValueTypes
public const string Json = "JSON"; // NText
/// <summary>
/// Text value (maps to text database type).
/// Text value (maps to nvarchar(max) database type).
/// </summary>
public const string Text = "TEXT"; // NText
@@ -55,7 +55,7 @@ public static class ValueTypes
public const string Time = "TIME"; // Date
/// <summary>
/// Text value (maps to varchar database type).
/// Text value (maps to nvarchar(512) database type).
/// </summary>
public const string String = "STRING"; // NVarchar

View File

@@ -2060,7 +2060,7 @@ internal sealed class DatabaseDataCreator
NodeId = -43,
EditorAlias = Constants.PropertyEditors.Aliases.CheckBoxList,
EditorUiAlias = "Umb.PropertyEditorUi.CheckBoxList",
DbType = "Nvarchar",
DbType = "Ntext",
});
}

View File

@@ -126,5 +126,6 @@ public class UmbracoPlan : MigrationPlan
// To 17.0.0
To<V_17_0_0.AddGuidsToAuditEntries>("{17D5F6CA-CEB8-462A-AF86-4B9C3BF91CF1}");
To<V_17_0_0.MigrateCheckboxListDataTypesAndPropertyData>("{EB1E50B7-CD5E-4B6B-B307-36237DD2C506}");
}
}

View File

@@ -0,0 +1,50 @@
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_17_0_0;
/// <summary>
/// Migrates data types based on the Umbraco.CheckBoxList property editor to store data in the text column without length restriction.
/// Also migrates the data for properties this property editor from the length restricted field (varcharValue - nvarchar(512)), to the
/// one without a restriction (textValue - nvarchar(max)).
/// </summary>
public class MigrateCheckboxListDataTypesAndPropertyData : AsyncMigrationBase
{
private readonly IDataTypeService _dataTypeService;
/// <summary>
/// Initializes a new instance of the <see cref="MigrateCheckboxListDataTypesAndPropertyData"/> class.
/// </summary>
public MigrateCheckboxListDataTypesAndPropertyData(IMigrationContext context, IDataTypeService dataTypeService)
: base(context) => _dataTypeService = dataTypeService;
/// <inheritdoc/>
protected override async Task MigrateAsync()
{
// Update the definition of the datatypes.
IEnumerable<IDataType> dataTypes = await _dataTypeService.GetByEditorAliasAsync(Constants.PropertyEditors.Aliases.CheckBoxList);
foreach (IDataType dataType in dataTypes)
{
dataType.DatabaseType = ValueStorageType.Ntext;
await _dataTypeService.UpdateAsync(dataType, Constants.Security.SuperUserKey);
}
// Copy from varcharValue to textValue and set varcharValue to null for all property data stored using data types based on
// the Umbraco.CheckBoxList property editor.
string sql = $@"
UPDATE umbracoPropertyData
SET textValue = varcharValue, varcharValue = NULL
WHERE propertyTypeId IN (
SELECT id
FROM cmsPropertyType
WHERE dataTypeId IN (
SELECT nodeId
FROM umbracoDataType
WHERE propertyEditorAlias = '{Constants.PropertyEditors.Aliases.CheckBoxList}'
)
)
AND varcharValue IS NOT NULL";
await Database.ExecuteAsync(sql);
}
}

View File

@@ -12,6 +12,7 @@ namespace Umbraco.Cms.Core.PropertyEditors;
/// </summary>
[DataEditor(
Constants.PropertyEditors.Aliases.CheckBoxList,
ValueType = ValueTypes.Text, // We use the Text value type to ensure we don't run out of storage space in the database field with large lists with multiple values selected.
ValueEditorIsReusable = true)]
public class CheckBoxListPropertyEditor : DataEditor
{