You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Guid正确插入SQLite的UNIQUEIDENTIFIER列避免值变更

问题原因

这个问题的核心是SQLite与.NET Guid的字节序差异,加上你直接用原生SQL插入时绕过了NHibernate的类型转换逻辑导致的:

SQLite本身没有原生的UNIQUEIDENTIFIER类型,NHibernate在处理Guid映射时,会自动转换.NET Guid和SQLite存储字节之间的字节序差异。.NET的Guid结构中,前三个字段(Data1、Data2、Data3)采用小端字节序存储,而当你直接用x'...'格式的十六进制字符串插入时,是按字节顺序直接写入数据库,没有经过NHibernate的转换处理,导致存储的字节序和.NET Guid的预期不匹配,最终查询出来的Guid值就变了。

比如你插入的十六进制x'7A2AC599D32D03458608E5C614301387',对应的字节序列是7A 2A C5 99 D3 2D 03 45 86 08 E5 C6 14 30 13 87,但.NET Guid读取时会把前4字节、接下来2字节、再接下来2字节反转(因为小端序),所以就变成了99c52a7a-2dd3-4503-8608-e5c614301387。

解决办法

方法1:使用参数化查询(推荐)

让NHibernate来处理Guid的类型转换,彻底避免手动处理字节序的麻烦。把Guid作为参数传入,而不是硬编码十六进制字符串:

// 定义你想要插入的目标Guid
var desiredGuid = new Guid("7A2AC599-D32D-0345-8608-E5C614301387");

// 编写带参数的SQL语句
var sql = @"INSERT INTO Patient (Id, RemoteId, FirstName, LastName, ChartNumber, LastScanDate, RowStatus, SearchName, DateUpdated, IsAllPropertiesSynced) 
            SELECT :patientId, 3072799, 'iRecord', 'Demo', '', '2017-06-04 07:53', 1, 'iRecordDemoiRecord', '2017-07-23 06:34', 1 
            WHERE NOT EXISTS(SELECT Id FROM Patient WHERE Id = :patientId);";

// 执行参数化查询
session.CreateSQLQuery(sql)
       .SetParameter("patientId", desiredGuid)
       .ExecuteUpdate();

这种方式下,NHibernate会自动根据SQLite的存储规则转换Guid的字节序,插入后查询得到的Guid就是你预期的值。

方法2:手动调整字节序(不推荐,易出错)

如果必须使用原生十六进制字符串插入,需要将.NET Guid的字节序转换成SQLite存储的格式。具体来说,你需要把目标Guid转换成.NET内部存储的字节序列,再转成十六进制字符串:

var desiredGuid = new Guid("7A2AC599-D32D-0345-8608-E5C614301387");
byte[] guidBytes = desiredGuid.ToByteArray();
// 转换成十六进制字符串(去掉分隔符)
string hexString = BitConverter.ToString(guidBytes).Replace("-", "");
// 此时hexString的值是 "99C52A7AD32D03458608E5C614301387"

然后把这个十六进制字符串用x'...'包裹插入到SQL中:

INSERT INTO Patient (Id, RemoteId, FirstName, LastName, ChartNumber, LastScanDate, RowStatus, SearchName, DateUpdated, IsAllPropertiesSynced) 
SELECT x'99C52A7AD32D03458608E5C614301387', 3072799, 'iRecord', 'Demo', '', '2017-06-04 07:53', 1, 'iRecordDemoiRecord', '2017-07-23 06:34', 1 
WHERE NOT EXISTS(SELECT Id FROM Patient WHERE Id = x'99C52A7AD32D03458608E5C614301387');

不过这种方法需要手动处理字节序,容易出错,所以更推荐用参数化查询的方式。

内容的提问来源于stack exchange,提问作者user3132295

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:39:15