Существует DataTable с первичным ключом для хранения информации о файлах. Случается, что есть 2 файла, которые различаются по именам с символами «4» и «4» (0xff14, символ «Fullwidth Digit Four»). DataTable не может включить их оба из-за неудачной уникальности. Однако в файловой системе Windows они, похоже, могут сосуществовать без каких-либо проблем.
Поведение, кажется, не зависит от настроек локали, я изменил «Region & Language-> Formats-> Format» с английского на японский, также изменился «язык для не-Unicode программ». Локаль была напечатана как «jp-JP», «en-GB». Всегда один и тот же результат.
Вопросы:
- что может быть менее навязчивым способом исправить это? Я мог бы перейти на использование контейнеров вместо System.Data. * Но я бы хотел этого избежать. Можно ли определить пользовательский компаратор для столбца или иным образом лучше проверить уникальность? Включение чувствительности к регистру (которое исправит это) может вызвать другие проблемы.
- есть ли вероятность, что некоторые глобальные настройки исправят это без перестройки программного обеспечения?
Демонстрационная программа с ошибкой:
using System;
using System.Data;
namespace DataTableUniqueness
{
class Program
{
static void Main(string[] args)
{
var changes = new DataTable("Rows");
var column = new DataColumn { DataType = Type.GetType("System.String"), ColumnName = "File" };
changes.Columns.Add(column);
var primKey = new DataColumn[1];
primKey[0] = column;
changes.PrimaryKey = primKey;
changes.Rows.Add("4.txt");
try
{
changes.Rows.Add("4.txt"); // throws the exception
}
catch (Exception e)
{
Console.WriteLine("Exception: {0}", e);
}
}
}
}
Исключение
Exception: System.Data.ConstraintException: Column 'File' is constrained to be unique. Value '4.txt' is already present.
at System.Data.UniqueConstraint.CheckConstraint(DataRow row, DataRowAction action)
at System.Data.DataTable.RaiseRowChanging(DataRowChangeEventArgs args, DataRow eRow, DataRowAction eAction, Boolean fireEvent)
at System.Data.DataTable.SetNewRecordWorker(DataRow row, Int32 proposedRecord, DataRowAction action, Boolean isInMerge, Boolean suppressEnsurePropertyChanged, Int32 position, Boolean fireEvent, Exception& deferredException)
at System.Data.DataTable.InsertRow(DataRow row, Int64 proposedID, Int32 pos, Boolean fireEvent)
at System.Data.DataRowCollection.Add(Object[] values)
PS: языковой стандарт выглядит так: