我正在尝试使用SQLite为.NET应用程序创建脱机缓存,该应用程序通常从服务器请求数据。我已经让数据库和表定义部分工作正常,并且在大多数情况下加载数据也工作得很好。我在我的测试表中缓存大约14,000行,数据大部分是正确的。问题是我似乎无法使用System.Data.SQLite
包装器来保存包含SQL时间戳值的byte[]
数据。
在其他任何事情之前,我应该注意到我意识到我可以将时间戳编码为其他东西(例如字符串或数字数据),但我更愿意使用本机BLOB功能,如果可能的话。那么让我们从那里开始吧。
表DDL现在看起来像这样:
CREATE TABLE Accounts
(
AccountID Int NOT NULL,
-- ...
Timestamp BLOB
)
但是我应该注意到,我还为VARBINARY
的列类型尝试了VARBINARY(4000)
,BINARY
,GENERAL
和Timestamp
,没有区别在结果中。
在插入时,我生成一个参数化的SQL命令,看起来像这样(为清晰起见,删除了很多字段):
INSERT INTO Accounts (AccountID, Timestamp)
SELECT @AccountID, @Timestamp
WHERE NOT EXISTS (SELECT 1 FROM Accounts WHERE AccountID = @AccountID)
参数@Timestamp
的{{1}}为DbType
且大小合适,插入行中的所有其他数据看起来都不错。但由于某种原因,Binary
保留为空。为什么会这样?
该值可验证为Timestamp
,具有预期内容。实际上,如果我将列类型更改为具有字符串亲和力并将其设为byte[8]
,则该列将存储“System.Byte []”。
列具有空值的事实是肯定的,首先只需使用SQLite数据库浏览器打开数据库文件并查看,然后第二,因为使用DbType.String
在第二个表中设置列会离开该字段null,当且仅当每行的Timestamp为空时,根据文档发生。
那么我还能错过什么?
**编辑**
全部注意:这是SQLite,而不是SQL CE。一些回应似乎使两者混淆。
答案 0 :(得分:2)
嗯,这真的很奇怪。当我意识到SQLite数据库浏览器对我说谎时,我有一个突破 - 它正在截断0x0处的二进制数据,这是我所有时间戳值的第一个字节,并将这些字段报告为空。我在尝试插入随机字节数据而不是时间戳后发现了这一点,此时我看到数据在GUI中出现。显然,它将数据视为以空字符结尾的字符串,而且我一开始并不知道它是天真的。
现在,我一直在使用SQLite数据库浏览器作为代理来调试问题(当我尝试读取时间戳值时,DBNull就出现了)。但当我回过头来看看我是否仍然从System.Data.SQLite包装器中获取DBNull时,我发现代码在仅使用原始时间戳数据运行时不再生成DBNull。在某些时候代码已经开始工作 - 我没有注意到,因为我愚蠢地依靠GUI来向我显示数据。
奇怪的是,我尝试回顾我的步骤,撤消我要做的事情,试图找出具体解决问题的方法。但是现在我无法重现原始错误,虽然它最初是绝对一致的(我无法绕过它的事实促使我首先使用GUI)!但我还没有将每个破碎的版本检查为源代码控制,所以此时我真的不知道问题是什么。
无论如何,至少有一个故事的道德,如果你不确定它的能力,就不要相信GUI。很难说我已经有多长时间没有工作代码,只是不知道它。