1

我正在尝试使用 SQLite 为通常从服务器请求数据的 .NET 应用程序创建离线缓存。我已经让数据库和表定义部分工作正常,并且在大多数情况下加载数据也工作正常。我在我的测试表中缓存了大约 14,000 行,并且数据大多是正确的。问题是我似乎无法让System.Data.SQLite包装器保留byte[]包含 SQL 时间戳值的数据。

首先,我应该注意我意识到我可以将时间戳编码为其他内容(例如字符串或数字数据),但如果可能的话,我更愿意使用本机 BLOB 功能。所以让我们从那里开始。

表 DDL 现在看起来像这样:

CREATE TABLE Accounts
(
    AccountID Int NOT NULL,
    -- ...
    Timestamp BLOB
)

但是我应该注意,我也尝试过VARBINARY, VARBINARY(4000),BINARYGENERALforTimestamp的列类型,结果没有区别。

在插入时,我生成了一个参数化的 SQL 命令,如下所示(为清楚起见,删除了许多字段):

INSERT INTO Accounts (AccountID, Timestamp)
SELECT @AccountID, @Timestamp
WHERE NOT EXISTS (SELECT 1 FROM Accounts WHERE AccountID = @AccountID)

该参数@Timestamp被赋予一个DbTypeBinary具有适当的大小,并且插入行中的所有其他数据看起来都很好。但由于某种原因,Timestamp保留为空。为什么会这样?

该值可验证为byte[8]具有预期内容的 a。实际上,如果我将列类型更改为具有字符串关联性并给它一个DbType.String,则该列将存储“System.Byte []”。

该列具有空值的事实是肯定的,首先只需使用 SQLite 数据库浏览器打开数据库文件并查看,其次是因为使用 a 在第二个表中设置列(SELECT MAX(Timestamp) FROM Accounts)会使字段为空,根据文档发生当且仅当每一行的时间戳为空。

那么我可能会错过什么?

** 编辑 **

请注意:这是SQLite,而不是 SQL CE。有些回应似乎混淆了两者。

4

1 回答 1

2

嗯,这真的很奇怪。当我意识到 SQLite 数据库浏览器对我撒谎时,我有了一个突破——它在 0x0 处截断二进制数据,这是我所有时间戳值的第一个字节,并将这些字段报告为空。我在尝试插入随机字节数据而不是时间戳后发现了这一点,此时我看到数据在 GUI 中通过。显然它将数据视为以空字符结尾的字符串,而我一开始并不知道它是如此幼稚。

现在,我一直在使用 SQLite 数据库浏览器作为代理来调试问题(当我尝试读取时间戳值时出现了 DBNulls)。但是当我回去查看是否仍然从 System.Data.SQLite 包装器中获取 DBNull 时,我发现当仅使用原始时间戳数据运行代码时,不再生成 DBNull。在某个时候,代码开始工作了——我只是没有注意到,因为我愚蠢地依赖 GUI 向我显示数据。

奇怪的是,我尝试追溯我的步骤,撤消我为找出解决问题的具体原因所做的事情。但是现在我无法重现最初的错误,尽管起初它是绝对一致的(我无法绕过它的事实促使我首先使用 GUI)!但是我并没有将每个损坏的版本都检查到源代码管理中,所以在这一点上我真的不知道问题是什么。

无论如何,这个故事至少有一个寓意,那就是,如果您不确定 GUI 的功能,请不要相信它。很难说我已经有了工作代码多久了,只是不知道而已。

于 2012-12-26T20:39:34.457 回答