SQLite.net表查询抛出NullReferenceException
本文关键字:NullReferenceException 查询 net SQLite | 更新日期: 2023-09-27 18:25:12
我正在使用以下代码行从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方法。但是,尽管这对我有效,但它并不能回答我的问题,因为我仍然想知道为什么这不起作用。
我很确定你不再参与这个项目了,但我会回答它,因为它可能会帮助仍在解决这个问题的人。
问题是你的实体,我不知道问题到底是什么,因为你没有在这里发布你的类。但基本上,您可能试图访问一个尚未从数据库中获取的属性。例如,我有一个具有两个属性的类:
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的属性还没有提取。
要解决此问题,必须先获取实体,然后通过此属性进行筛选。这基本上就是您在编辑2中所做的。您已获取所有实体,然后进行筛选。
也许我太新了,不知道我在说什么,但我认为您的上一个示例在调用ToListAsync
之前只需要一个await
语句。
var query = Connection.Table<WorkDay>().Where(wd => wd.Date >= @from && wd.Date <= to);
return await query.ToListAsync().ConfigureAwait(false);
不确定第一个问题的具体情况,但我认为这与Where语句生成的TableAsyncQuery对象有关,在ToListAsync在另一个线程上调用它之前,它没有完全初始化。
为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不能在数据库查询中使用。。表中没有这样的字段。