如何在 Sqlite.Net 中的 where 子句中使用 DateTime

How to use a DateTime in a where clause in Sqlite.Net

我正在编写一个使用 Sqlite.Net 的移动应用程序 我正在尝试使用 DateTime 属性 和 LINQ 来过滤我的 Table SQL

我有如下一段代码:

 var validDates = Database.Connection.Table<Dates>()
        .Where(x => x.StartDate <= DateTime.Today && x.EndDate >= DateTime.Today)
       .ToList();

但是这会抛出一个 对象引用未设置到对象的实例 而且堆栈跟踪似乎表明错误在 Sqlite.Net 库中,这导致我相信我没有正确使用 DateTimes

Warning: Unhandled exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object. 09-28 13:01:24.293 W/Xamarin.Insights(31238): at SQLite.Net.TableQuery1[T].CompileExpr (System.Linq.Expressions.Expression expr, System.Collections.Generic.List1[T] queryArgs) [0x00613] in <8f2bb39aeff94a30a8628064be9c7efe>:0 09-28 13:01:24.293 W/Xamarin.Insights(31238): at SQLite.Net.TableQuery1[T].CompileExpr (System.Linq.Expressions.Expression expr, System.Collections.Generic.List1[T] queryArgs) [0x0064b] in <8f2bb39aeff94a30a8628064be9c7efe>:0 09-28 13:01:24.293 W/Xamarin.Insights(31238): at SQLite.Net.TableQuery1[T].CompileExpr (System.Linq.Expressions.Expression expr, System.Collections.Generic.List1[T] queryArgs) [0x00027] in <8f2bb39aeff94a30a8628064be9c7efe>:0 09-28 13:01:24.293 W/Xamarin.Insights(31238): at SQLite.Net.TableQuery1[T].CompileExpr (System.Linq.Expressions.Expression expr, System.Collections.Generic.List1[T] queryArgs) [0x00027] in <8f2bb39aeff94a30a8628064be9c7efe>:0 09-28 13:01:24.293 W/Xamarin.Insights(31238): at SQLite.Net.TableQuery1[T].GenerateCommand (System.String selectionList) [0x0006d] in <8f2bb39aeff94a30a8628064be9c7efe>:0 09-28 13:01:24.293 W/Xamarin.Insights(31238): at SQLite.Net.TableQuery1[T].GetEnumerator () [0x00008] in <8f2bb39aeff94a30a8628064be9c7efe>:0 09-28 13:01:24.293 W/Xamarin.Insights(31238): at System.Collections.Generic.List1[T]..ctor (System.Collections.Generic.IEnumerable1[T] collection) [0x00073] in /Users/builder/data/lanes/3819/c1d1c79c/source/mono/mcs/class/referencesource/mscorlib/system/collections/generic/list.cs:98 09-28 13:01:24.293 W/Xamarin.Insights(31238): at System.Linq.Enumerable.ToList[TSource] (System.Collections.Generic.IEnumerable`1[T] source) [0x00011] in /Users/builder/data/lanes/3819/c1d1c79c/source/mono/mcs/class/referencesource/System.Core/System/Linq/Enumerable.cs:861

像这样作为一个 sql statemnet 来工作:

 var query = string.Format("Select * from [Dates.Dates] where StartDate<=date('{0:yyyy-MM-dd}') and EndDate>=date('{1:yyyy-MM-dd}')", DateTime.Today, DateTime.Today);

但是有没有一种方法可以使用 LINQ to SQL 来执行 DateTime 查询?

Here is the source and method it is erroring in

额外信息

我的 StoreDateTimeAsTicks 设置设为 True

我对 StartDateEndDate 的定义都是 DateTimes

我的 Dates class 看起来像这样:

[Table("Dates.Dates")]
public class Dates : BaseModel
{
    public Dates()
    {
        //Don't fire notifications by default, since
        //they make editing the properties difficult.
        this.NotifyIfPropertiesChange = false;
    }

    [PrimaryKey]
    [NotNull]
    [AutoIncrement, Column("Id")]
    public int Id 
    { 
        get { return Id_private; }
        set { SetProperty(Id_private, value, (val) => { Id_private = val; }, Id_PropertyName); }
    }
    public static string Id_PropertyName = "Id";
    private int Id_private;

    [NotNull]
    [Column("Name")]
    public string Name 
    { 
        get { return Name_private; }
        set { SetProperty(Name_private, value, (val) => { Name_private = val; }, Name_PropertyName); }
    }
    public static string Name_PropertyName = "Name";
    private string Name_private;

    [NotNull]
    [Column("StartDate")]

    // The actual column definition, as seen in SQLite
    public string StartDate_raw { get; set; }

    public static string StartDate_PropertyName = "StartDate";

    // A helper definition that will not be saved to SQLite directly.
    // This property reads and writes to the _raw property.
    [Ignore]
    public DateTime StartDate { 
        // Watch out for time zones, as they are not encoded into
        // the database. Here, I make no assumptions about time
        // zones.
        get { return StartDate_raw != null ? DateTime.Parse(StartDate_raw) : StartDate = DateTime.Now; }
        set { SetProperty(StartDate_raw, StartDate_ConvertToString(value), (val) => { StartDate_raw = val; }, StartDate_PropertyName); }
    }

    // This static method is helpful when you need to query
    // on the raw value.
    public static string StartDate_ConvertToString(DateTime date)
    {    
        return date.ToString("yyyy-MM-dd");     
    }           

    [NotNull]
    [Column("EndDate")]

    // The actual column definition, as seen in SQLite
    public string EndDate_raw { get; set; }

    public static string EndDate_PropertyName = "EndDate";

    // A helper definition that will not be saved to SQLite directly.
    // This property reads and writes to the _raw property.
    [Ignore]
    public DateTime EndDate { 
        // Watch out for time zones, as they are not encoded into
        // the database. Here, I make no assumptions about time
        // zones.
        get { return EndDate_raw != null ? DateTime.Parse(EndDate_raw) : EndDate = DateTime.Now; }
        set { SetProperty(EndDate_raw, EndDate_ConvertToString(value), (val) => { EndDate_raw = val; }, EndDate_PropertyName); }
    }

    // This static method is helpful when you need to query
    // on the raw value.
    public static string EndDate_ConvertToString(DateTime date)
    {    
        return date.ToString("yyyy-MM-dd");     
    }
}

试试这个:

string dateToday = DateTime.Today;
var validDates = Database.Connection.Table<Dates>().Where(x => x.StartDate <= dateToday && x.EndDate >= dateToday).ToList();

所以问题是我的 class 中的 StartDateEndDate 属性不是 列。它们只是真正的 StartDate_RawEndDate_Raw 属性的包装器。 strings.

因为 Raw 列是字符串,这意味着我也不能使用 LINQ 过滤数据库到 SQL 使用字符串日期,所以我是很困惑。

我的日期存储为字符串的限制是我使用的某些名为 Zumero 的第三方软件的限制。如果我没有使用它,我会把我的 table 模式改为 int。

所以我最终做的是将 SQL 数据库中的所有 DateTime 列更改为 Ticks 并存储为 Ints这意味着我可以将我的 string DateTime 属性 更改为 int 并使用 LINQ to SQL 像这样:

var validDates = Database.Connection.Table<Dates>()
        .Where(x => x.StartDate_Raw <= DateTime.Today && x.EndDate_Raw >= DateTime.Today)
       .ToList();