从SQLite中提取数据时,Linq查询抛出NullReferenceException,为什么?

时间:2017-05-21 17:22:39

标签: c# asp.net linq linq-to-sql

我试图通过以下查询从SQLite数据库中提取数据:

DateTime Dzien = new DateTime(ticks ?? 0);
    var assinged = Data.Tasks.ToList();
    var assign =  assinged.Where(t => t.AssignedId ==
                              Data.AssignedTasks.FirstOrDefault(d => d.Date.Date == Dzien.Date).Id).ToList();

但它引发了一个例外:

NullReferenceException:未将对象引用设置为对象的实例。 HomeController.cs第37行中的PiCoreSQLite.Controllers.HomeController +<> c__DisplayClass3_0.b__0(任务t)

数据对象是数据库上下文,而任务是包含任务对象的DbSet。

我尝试删除ToList(),但查询没有返回任何内容。但是,当在asp.net .cshtml视图中使用类似的查询时,它确实有效并返回数据:

 @{
    var zrobione =
        from completed in Model.Item1.Where(t => t.AssignedId == 
        Model.Item3.FirstOrDefault(d => d.Date.Date == DateTime.Today).Id)
        group completed by completed.Categories;
}

我尝试用流利的语法重写查询,但它仍然会引发异常。

我的问题是:为什么抛出异常以及如何解决它?

2 个答案:

答案 0 :(得分:1)

  

为什么会抛出此异常?

问题是由以下声明引起的:

Data.AssignedTasks.FirstOrDefault(d => d.Date.Date == Dzien.Date)

FirstOrDefault方法返回您应用此方法的序列中的第一项,该方法满足您在此方法中传递的谓词,谓词如下:

d => d.Date.Date == Dzien.Date

如果未找到任何此类项目,则会返回null(更通常会返回您要查找的对象类型的默认值。所以,如果您是查找int默认值为0.如果是引用类型,则默认值为null)。

话虽如此,很明显返回null然后您尝试访问空引用的Id属性...因此您收到此错误消息。

  

我们如何处理这个?

一种方法可能如下:

var assign =  assinged.Where(t => t.AssignedId ==
                                (Data.AssignedTasks
                                     .FirstOrDefault(d => d.Date.Date == Dzien.Date)?.Id ?? -1))
                      .ToList();

在上面的代码中我假设 AssignedId只取正值或零值。如果不是这样的话,你可以适当地处理这个问题。

  

以上是如何运作的?

正如我们已经提到的,FirstOrDefault将返回对第一个找到的对象的引用,该对象满足您传递的谓词或null。因此,为了安全起见,我们使用空条件运算符?.。如果你得到null以外的任何引用,你可以安全地读取Id,否则没有意义,结果是null。然后应用空合并运算符??。当此操作符与null不同时返回左侧值,否则返回右侧值。

答案 1 :(得分:0)

首先,您需要确定究竟是什么引发了异常。将代码分成几个简单的步骤并进行调试。什么失败会告诉你如何妥善处理它。

此外,值得注意的是,您的代码的第一个示例根本不是LINQ to SQL,而第二个示例是。这是差异,也是他们工作方式不同的原因之一。顺便说一下,应该是预期的。

最有可能install plugins返回null,然后将Data.AssignedTasks.FirstOrDefault(d => d.Date.Date == Dzien.Date)拉出来会引发异常。在第二个示例中,整个表达式被转换为SQL查询,这就是它工作正常的原因。