Binary(16) 字段正在截断 Guid 的尾随零
Binary(16) field Is truncating Guid's trailing zeros
在 C# 中,我有一个名为 UniqueId 的 byte[]
字段。我将此字段作为 Binary(16) 存储在 SQL 服务器数据库 (EF6) 中。
我注意到有时存储的 guid 是 15 字节而不是 16 字节。当我从数据库中检索值后执行 var guid = new Guid(uniqueId)
时,这会导致以下异常:
System.ArgumentException : Byte array for GUID must be exactly 16
bytes long.
对此进行调查后,我注意到只要我生成的 guid 在十六进制末尾包含“00”,SQL 就会截断它!
示例:
生成的 Guid(通过 Guid.NewGuid): FF96F954777E8941A04774CD157C5C00(16 字节)
存储在SQL服务器中的二进制文件(16):0xFF96F954777E8941A04774CD157C5C(15字节)
如果您注意到,最后的 00
被截断了。因此,如果我查询该字段并尝试将其字节转换为 Guid,我将得到 System.ArgumentException
.
还有其他人遇到这个问题吗?解决方法是什么?我正在考虑 Guid
的包装器,它一直生成 guid 直到它没有尾随零,但这看起来很老套。
更新 1:由于你们要求,我 运行 SQL 分析器,这是由 EF(删节版)生成的 SQL:
exec sp_executesql N'INSERT [dbo].[customers]([UniqueId])
VALUES (@0)',N'@0 varbinary(max)',@0=0xFF96F954777E8941A04774CD157C5C00
如果列的 ANSI_PADDING
设置为 OFF
且列允许 NULL
(demo),则 BINARY(16)
会出现此行为。
理想情况下,修复它会涉及更改 table 定义,以便该列使用 uniqueidentifier
数据类型或至少启用 ANSI_PADDING
。
要更改 ANSI_PADDING
语义将涉及 SET ANSI_PADDING ON
然后添加一个新的 binary(16)
列 - 从旧列填充它,然后删除并重命名。这是如果您的应用程序可以容忍可能的列重新排序,如果它无法处理这种重新排序并且 UniqueId
不是 table 中的最后一列,您将需要创建一个新的 table 并迁移所有数据。
如果您不想更改数据库设置,您可以随时填充从数据库返回的内容,例如
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);
在 C# 中,我有一个名为 UniqueId 的 byte[]
字段。我将此字段作为 Binary(16) 存储在 SQL 服务器数据库 (EF6) 中。
我注意到有时存储的 guid 是 15 字节而不是 16 字节。当我从数据库中检索值后执行 var guid = new Guid(uniqueId)
时,这会导致以下异常:
System.ArgumentException : Byte array for GUID must be exactly 16 bytes long.
对此进行调查后,我注意到只要我生成的 guid 在十六进制末尾包含“00”,SQL 就会截断它!
示例:
生成的 Guid(通过 Guid.NewGuid): FF96F954777E8941A04774CD157C5C00(16 字节)
存储在SQL服务器中的二进制文件(16):0xFF96F954777E8941A04774CD157C5C(15字节)
如果您注意到,最后的 00
被截断了。因此,如果我查询该字段并尝试将其字节转换为 Guid,我将得到 System.ArgumentException
.
还有其他人遇到这个问题吗?解决方法是什么?我正在考虑 Guid
的包装器,它一直生成 guid 直到它没有尾随零,但这看起来很老套。
更新 1:由于你们要求,我 运行 SQL 分析器,这是由 EF(删节版)生成的 SQL:
exec sp_executesql N'INSERT [dbo].[customers]([UniqueId])
VALUES (@0)',N'@0 varbinary(max)',@0=0xFF96F954777E8941A04774CD157C5C00
如果列的 ANSI_PADDING
设置为 OFF
且列允许 NULL
(demo),则 BINARY(16)
会出现此行为。
理想情况下,修复它会涉及更改 table 定义,以便该列使用 uniqueidentifier
数据类型或至少启用 ANSI_PADDING
。
要更改 ANSI_PADDING
语义将涉及 SET ANSI_PADDING ON
然后添加一个新的 binary(16)
列 - 从旧列填充它,然后删除并重命名。这是如果您的应用程序可以容忍可能的列重新排序,如果它无法处理这种重新排序并且 UniqueId
不是 table 中的最后一列,您将需要创建一个新的 table 并迁移所有数据。
如果您不想更改数据库设置,您可以随时填充从数据库返回的内容,例如
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);