Двоичное (16) поле обрезает конечные нули Гуида - PullRequest
3 голосов
/ 05 апреля 2019

В C # у меня есть поле byte[] с именем UniqueId. Я сохраняю это поле как двоичное (16) в базе данных SQL Server (EF6).

Я заметил, что иногда сохраненный guid составляет 15 байтов вместо 16 байтов. Это вызывает следующее исключение, когда я делаю var guid = new Guid(uniqueId) после получения значения из БД:

System.ArgumentException: байтовый массив для GUID должен быть ровно 16 длина байта.

После изучения этого я заметил, что всякий раз, когда мой сгенерированный guid содержит "00" в конце гекса, SQL обрезает его!

Пример:

Сгенерированный Guid (через Guid.NewGuid): FF96F954777E8941A04774CD157C5C00 (16 байтов)

Сохраненный двоичный код (16) в SQL Server : 0xFF96F954777E8941A04774CD157C5C (15 байт)

Если вы заметили, 00 в конце усекается. В результате, если я сделаю запрос в этом поле и попытаюсь преобразовать его байты в Guid, я получу System.ArgumentException.

Кто-нибудь еще испытывает эту проблему? Какой обходной путь? Я думаю об обёртке для Guid, которая продолжает генерировать направляющие, пока у нее нет конечных нулей, но это кажется хакерским.

Обновление 1: так как вы, ребята, запросили это, я запустил средство профилирования SQL, и это SQL, сгенерированный EF (сокращенная версия):

exec sp_executesql N'INSERT [dbo].[customers]([UniqueId])
VALUES (@0)',N'@0 varbinary(max)',@0=0xFF96F954777E8941A04774CD157C5C00

Ответы [ 2 ]

6 голосов
/ 05 апреля 2019

Такое поведение наблюдается при BINARY(16), если для столбца установлено значение ANSI_PADDING OFF, а для столбца разрешено NULL ( demo ).

Исправление может привести кВ идеале необходимо изменить определение таблицы, чтобы столбец использовал тип данных uniqueidentifier или, по крайней мере, включил ANSI_PADDING.

Чтобы изменить семантику ANSI_PADDING, потребуется SET ANSI_PADDING ON и добавление нового столбца binary(16).- заполнить его из старого столбца, а затем сбросить и переименовать.И это в том случае, если ваше приложение может допустить возможное переупорядочение столбцов, если оно не может справиться с этим переупорядочением, и UniqueId не является последним столбцом в таблице, вам потребуется создать новую таблицу и перенести все данные между собой.

0 голосов
/ 05 апреля 2019

Если вы не хотите изменять настройки базы данных, вы всегда можете просто добавить то, что возвращается из базы данных, например,

byte[] uniqueId = new byte[15]; //however this comes back from the db;
byte[] uniqueIdPadded = new byte[16];
uniqueId.CopyTo(uniqueIdPadded, 0);
var guid = new Guid(uniqueIdPadded);
...