SQLite.net表查询抛出NullReferenceException

时间:2014-09-30 22:40:23

标签: c# sqlite async-await sqlite-net

我正在使用以下代码行来查询SQLite数据库中给定表中的一些数据(平台是WP81,但我想这在这里无关紧要。)

return await Connection.Table<WorkDay>().Where(wd => wd.Date >= @from && wd.Date <= to).ToListAsync().ConfigureAwait(false);

当我执行代码时,我在Where子句中得到NullReferenceException。当我删除where条件时一切正常。

return await Connection.Table<WorkDay>().ToListAsync().ConfigureAwait(false);

为了确保我的表中的所有条目都有效并且Date列中没有空值,我使用SQL工具查看SQLite数据库。

因为我无法调试lambda表达式,所以我有点坚持如何在这里找到问题。我的假设是由于异步处理而出现问题。

修改 这是异常的确切堆栈跟踪

{System.NullReferenceException: Object reference not set to an instance of an object.
   at SQLite.Net.TableQuery`1.CompileExpr(Expression expr, List`1 queryArgs)
   at SQLite.Net.TableQuery`1.CompileExpr(Expression expr, List`1 queryArgs)
   at SQLite.Net.TableQuery`1.CompileExpr(Expression expr, List`1 queryArgs)
   at SQLite.Net.TableQuery`1.GenerateCommand(String selectionList)
   at SQLite.Net.TableQuery`1.GetEnumerator()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at SQLite.Net.Async.AsyncTableQuery`1.<ToListAsync>b__0()
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at TimeStamp.Core.Services.DataService.<GetWorkDays>d__c.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at TimeStamp.Core.ViewModel.MainViewModel.<LoadWorkDays>d__1a.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>b__3(Object state)}

编辑2:

我玩得更多,并想出以下内容。

var query = Connection.Table<WorkDay>().Where(wd => wd.Date >= @from && wd.Date <= to);
return query.ToListAsync().ConfigureAwait(false);

执行此语句时,它实际上在ToListAsync()方法中而不是Where方法中断。但是,这也无济于事。

后来我尝试了以下实际工作。

var result = await Connection.Table<WorkDay>().ToListAsync().ConfigureAwait(false);
return result.Where(wd => wd.Date >= @from && wd.Date <= to).ToList();

所以我做的是实际分离Where方法。但是虽然这对我有用但它没有回答我的问题,因为我仍然想知道为什么这不起作用。

3 个答案:

答案 0 :(得分:1)

也许我太新了,不知道我在说什么,但我认为你的最后一个例子在await电话之前需要ToListAsync声明。

var query = Connection.Table<WorkDay>().Where(wd => wd.Date >= @from && wd.Date <= to);
return await query.ToListAsync().ConfigureAwait(false);

不确定第一个问题的具体细节,但我认为它与TableAsyncQuery对象有关,Where语句产生,而不是在ToListAsync在另一个线程上调用它之前完全初始化。

答案 1 :(得分:0)

我敢肯定,您将不再从事此项目,但我将作答,因为它可能会帮助仍在努力解决此问题的人。

问题是您的实体,我不知道问题出在哪里,因为您没有在此处发布课程。但是基本上,您可能正在尝试访问尚未从数据库中获取的属性。例如,我有一个具有两个属性的类:

public class MyClass
{
      public DateTime Date { get; set; } // You're saving this property in the database
      public bool IsLate => Date < DateTime.Today; // This property is not be saving, and probably is the cause of your exception
}

我不知道为什么SQLite会这样做,但是当它查询您的实体时,如果您在查询中通过 IsLate 属性进行过滤,则由于 Date < / strong>属性尚未获取。

要解决此问题,您必须先获取实体,然后按此属性过滤。这基本上就是您在 EDIT 2 中所做的。您已经获取了所有实体,然后进行了过滤。

答案 2 :(得分:0)

为Daniel Cunha答案添加更多细节 我在cProduct类中有这个

    [PrimaryKey, AutoIncrement]
    public int rowid
    {
        get => _rowid;
        set => _rowid = value;
    }

    [Ignore]
    public int ID => rowid; // just for convinience

此查询有效 product.Product = dbConnection.Table<cProduct>().Where(s => s.rowid == product.ProductID).FirstOrDefault();

但这会失败,并且引用引用为空

product.Product = dbConnection.Table<cProduct>().Where(s => s.ID == product.ProductID).FirstOrDefault();

s.ID不能在数据库查询中使用。表中没有此类字段。