【问题标题】:nullable object must have a value even after "HasValue" check即使在“HasValue”检查之后,可为空的对象也必须有一个值
【发布时间】:2019-01-22 00:49:48
【问题描述】:

我有这个 LINQ to SQL 查询:

int? ID = null;
var query = from t in db.things where (!ID.HasValue || t.ID == ID.Value) select t;

现在在常规 LINQ 中,这可以正常工作,但在 LINQ to SQL 中会引发“可为空的对象必须具有值”异常。

LINQ to SQL 是否会对我的 null 检查做出一些奇怪的解释?如果是这样,我该如何正确实现这个功能?

【问题讨论】:

  • 您检查 t.ID 是否为空?
  • t.ID 是一个 int,所以它不能为空 - 它也是数据库中的主键
  • 仍然t 可以为空。看起来IDt 的一个属性
  • 因为 t 来自数据库,所以它永远不会为空。我也使用断点确认了这一点 - 异常肯定来自对 ID.Value 的调用
  • 将 t.ID 的定义更改为 int?。看起来数据库可以为空,但你的类不能。

标签: c# linq-to-sql nullable


【解决方案1】:

据我所知,您是正确的 Linq to SQL 对此存在问题。根据对这个问题的回答:Linq to Sql is null in Where clause 你想要这样的东西。

int? ID = null;
var query = from t in db.things where (!ID.HasValue || (ID.HasValue && t.ID == ID.Value)) select t;

【讨论】:

  • 谢谢 Ben,看起来很有希望,但我尝试了这个并得到了同样的错误
【解决方案2】:

你可以这样做:

int? ID = null;
if(ID.HasValue)
{
   var query = from t in db.things where (t.ID == ID.Value) select t;
}
else //when ID is null
{
   var query = from t in db.things select t;
}

或者它可以在一行中完成:

var query = ID.HasValue ? from t in db.things where (t.ID == ID.Value)select t : from t in db.things select t;

【讨论】:

  • 这不太对。当 ID 为空时,它应该选择所有行(至少问题中是这样写的)。
  • 应该去else { var query = from t in db.things select t}
  • 是的,这是一个很好的解决方案,实际查询比我的问题中的示例要长一些,所以可能会有一些代码重复。然而,这绝对是一个选择
【解决方案3】:

使用调试器后,发现 LINQ to SQL 不理解 null 检查,只是呈现如下 SQL:

SELECT [t0]
FROM [dbo].[things] AS [t0]
WHERE [t0].[ID] = @p0

因此,当它解析@p0 的值时,它会尝试评估ID.Value,而不考虑我的空检查。

我使用GetValueOrDefault()解决了这个问题:

int? ID = null;
var query = from t in db.things where (!ID.HasValue || t.ID == ID.GetValueOrDefault()) select t;

在这种情况下,它能够理解 where 子句,因为变量总是会评估为某种值。

【讨论】:

    猜你喜欢
    • 2010-12-26
    • 1970-01-01
    • 2012-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多