Search code examples
sqlitedatetimeservicestackormlite-servicestack

Servicestack - OrmLite query by date on SQLite32 database does not return any results


I ran into something strange today by query-ing an 32 bits SQLite embedded database using ServiceStack ORMLite (Testing on Windows 2012 Server, .NET Framework 4.0).

Consider the following test queries:

var dateMinimum = DateTime.Now.Subtract(_doNotProcessQueueItemWhenOlderThanHours);
using (var db = DbConnectionFactory.OpenDbConnection())
{
    var queueItemsTest1 = db.Select<ProcessQueue>(pc => (pc.Status == ProcessingStatus.Failed.ToString()) && (pc.DateCreated > dateMinimum)).ToList();
    var queueItemsTest2 = db.Select<ProcessQueue>(pc => (pc.Status == ProcessingStatus.Failed.ToString())).ToList();
    var queueItemsTest3 = db.Select<ProcessQueue>(pc => (pc.DateCreated > dateMinimum)).ToList();


    var queueItemsUnparsed = db.Select<ProcessQueue>().ToList();
    var queueItems = new List<ProcessQueue>();
    foreach (var queueItemUnparsed in queueItemsUnparsed)
    {
        if ((queueItemUnparsed.Status == ProcessingStatus.Failed.ToString()) && (queueItemUnparsed.DateCreated > dateMinimum))
        {
            queueItems.Add(queueItemUnparsed);
        }
    }
}

public class ProcessQueue
{
    [AutoIncrement]
    public int Id { get; set; }
    public DateTime DateCreated { get; set; }
    public string Status { get; set; }
}

What is strange that:

  • queueItemsTest1 returns nothing
  • queueItemsTest2 returns all correct rows
  • queueItemsTest3 returns nothing
  • The foreach construction returns the correct rows.

Is there some way to log what is going on inside the database?

I think it is SQLite related because I have another queue which talks to SQL server and this works. I am using SQLite because this queue must be embedded and could not find a way to make ORMLite work with SQL Compact.


Solution

  • Is there some way to log what is going on inside the database?

    The simplest way is to use Console.WriteLine(db.GetLastSql());

    So in your case:

    var queueItemsTest1 = db.Select<ProcessQueue>(pc => (pc.Status == ProcessingStatus.Failed.ToString()) && (pc.DateCreated > dateMinimum)).ToList();
    Console.WriteLine(db.GetLastSql());
    
    var queueItemsTest2 = db.Select<ProcessQueue>(pc => (pc.Status == ProcessingStatus.Failed.ToString())).ToList();
    Console.WriteLine(db.GetLastSql());
    
    var queueItemsTest3 = db.Select<ProcessQueue>(pc => (pc.DateCreated > dateMinimum)).ToList();
    Console.WriteLine(db.GetLastSql());
    

    Then you should be able to use the SQL output to determine what query it is building. If I were to hazard a guess I would say it's to do with the Date handling.


    You can't use the DateTime object because SQLite does not support a corresponding format.

    From the SQLite documentation:

    SQLite does not have a storage class set aside for storing dates and/or times. Instead, the built-in Date And Time Functions of SQLite are capable of storing dates and times as TEXT, REAL, or INTEGER values:

    • TEXT as ISO8601 strings ("YYYY-MM-DD HH:MM:SS.SSS").
    • REAL as Julian day numbers, the number of days since noon in Greenwich on November 24, 4714 B.C. according to the proleptic Gregorian calendar.
    • INTEGER as Unix Time, the number of seconds since 1970-01-01 00:00:00 UTC.

    Applications can chose to store dates and times in any of these formats and freely convert between formats using the built-in date and time functions.

    Using DateTime.Ticks should provide an appropriate long.