I am trying to use SQLite to create an offline cache for a .NET application which normally requests data from a server. I’ve already got the database and table definition part working fine, and for the most part loading the data is working fine, too. I’m caching about 14,000 rows in my test table and the data is mostly correct. The problem is that I can’t seem to get the System.Data.SQLite wrapper to persist the byte[] data that comprises a SQL timestamp value.
Before anything else, I should note that I realize I could encode the timestamp as something else (string or numeric data, for instance), but I’d much rather use the native BLOB functionality instead, if possible. So let’s start there.
The table DDL looks like this, now:
CREATE TABLE Accounts
(
AccountID Int NOT NULL,
-- ...
Timestamp BLOB
)
However I should note that I have also tried VARBINARY, VARBINARY(4000), BINARY, and GENERAL for Timestamp‘s column type, with no difference in the results.
At the time of insert, I generate a parameterized SQL command that looks like this (lots of fields removed for clarity):
INSERT INTO Accounts (AccountID, Timestamp)
SELECT @AccountID, @Timestamp
WHERE NOT EXISTS (SELECT 1 FROM Accounts WHERE AccountID = @AccountID)
The parameter @Timestamp is given a DbType of Binary and has the proper size, and all the other data in the inserted row looks fine. But for some reason, Timestamp is left null. Why might this be?
The value is verifiably a byte[8] with the expected contents. In fact, if I change the column type to have a string affinity and give it a DbType.String, the column will store “System.Byte[]”.
The fact that the column has a null value is certain, first by simply opening the database file using the SQLite Database Browser and looking, and second because setting a column in a second table using a (SELECT MAX(Timestamp) FROM Accounts) leaves the field null, which according to the docs happens if and only if every row’s Timestamp is null.
So what could I be missing?
** EDIT **
Note to all: this is SQLite, not SQL CE. Some responses seem to confuse the two.
Well, this is really odd. I had a breakthrough when I realized that SQLite Database Browser was lying to me– it was truncating binary data at 0x0, which was the first byte of all my timestamp values, and reporting those fields as empty. I discovered this after trying inserting random byte data instead of the timestamps, at which point I saw the data come through in the GUI. Obviously it’s treating the data as null-terminated strings, and I didn’t know it was that naive at first.
Now, I had been using the SQLite Database Browser as a proxy to debug the problem (which was DBNulls showing up when I tried to read the timestamp values out). But when I went back to see if I was still getting DBNull from the System.Data.SQLite wrapper, I discovered that the code, when run with just the original timestamp data in place, was no longer producing DBNulls. At some point the code had started working– I just hadn’t noticed because I foolishly relied on the GUI to show me the data.
The odd part is, I tried retracing my steps, undoing things I’d done to try to figure out what specifically had fixed the problem. But now I can’t reproduce the original error, though it was absolutely consistent at first (the fact that I couldn’t get around it was what prompted me to use a GUI in the first place)! But I haven’t been checking each broken version into source control, so at this point I really don’t know what the issue was.
Anyway, there’s at least one moral of the story, which is, don’t trust the GUI if you don’t know its capabilities for sure. Hard to say how long I’ve already had working code and just not known it.