Binary(16)字段截断了Guid的尾随零

时间:2019-04-05 15:07:57

标签: c# sql sql-server entity-framework guid

在C#中,我有一个byte[]字段,称为UniqueId。我将此字段作为Binary(16)存储在SQL Server数据库(EF6)中。

我注意到有时存储的guid是15字节而不是16字节。当我从数据库中检索值后执行var guid = new Guid(uniqueId)时,这会导致以下异常:

  

System.ArgumentException:GUID的字节数组必须正好为16   长字节。

在对此进行调查之后,我注意到,只要生成的guid在十六进制末尾包含“ 00”,SQL就会将其截断!

示例:

生成的Guid(通过Guid.NewGuid)::FF96F954777E8941A04774CD157C5C00(16字节)

在SQL Server中存储二进制(16):0xFF96F954777E8941A04774CD157C5C(15字节)

如果您注意到,末尾的00将被截断。结果,如果我查询该字段并尝试将其字节转换为Guid,我将得到一个System.ArgumentException

还有其他人遇到这个问题吗?解决方法是什么?我正在考虑使用Guid的包装程序,该包装程序会一直生成guid,直到没有尾随零为止,但这似乎很hack。

更新1:由于你们的要求,我运行了SQL事件探查器,这是EF(节略版)生成的SQL:

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

2 个答案:

答案 0 :(得分:6)

如果该列的BINARY(16)设置为ANSI_PADDING并且该列允许使用OFFdemo),则您会看到NULL的这种行为。

修复该问题最好是更改表定义,以便该列使用uniqueidentifier数据类型或至少打开ANSI_PADDING

要更改ANSI_PADDING的语义,将涉及SET ANSI_PADDING ON,然后添加一个新的binary(16)列-从旧列中填充它,然后拖放并重命名。这是您的应用程序可以忍受列的可能重新排序,如果它不能应对这种重新排序并且UniqueId不是表中的最后一列,则需要创建一个新表并在所有表之间迁移所有数据

答案 1 :(得分:0)

如果您不想更改数据库设置,则始终可以填充从数据库返回的内容,例如

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);