这真的是一个可能的InvalidOperationException吗?

时间:2010-07-15 20:28:57

标签: linq-to-sql resharper nullreferenceexception

我有一个Linq2Sql查询,如下所示:

var data = from d in dc.GAMEs
    where (d.GAMEDATE + d.GAMETIME.Value.TimeOfDay) >= DateTime.Now
        && d.GAMESTAT == 'O' && d.GAMETYPE == 0 select d;

Resharper以蓝色突出显示“d.GAMETIME.Value.TimeOfDay”并告诉我这是一个可能的System.InvalidOperationException。虽然我知道如果它是C#代码,引用Value而不检查它是否有值,我不确定Linq查询是否正确。

生成的实际SQL看起来很可怕,并且让我想要烧掉我的眼睛,但我看不出任何看起来像是空引用的东西。我可以放心地忽略这个吗?

(暂时忽略其他问题,例如是否返回预期结果)

编辑:

进一步思考,我可以看到上面的内容如何在LinqToObjects查询中引起异常,可能还有其他类型(XML?)。所以,是的,我认为Resharper只是安全。

2 个答案:

答案 0 :(得分:2)

在处理表达式树时(如此LINQ to SQL查询),它完全取决于所使用的LINQ提供程序(在您的情况下是LINQ to SQL)。因此,Resharper(几乎)不可能对您的查询说任何有用的内容。我认为它只是将此代码解释为普通的C#代理。我会说可以安全地忽略,但也许可以为下一个开发者添加评论。

答案 1 :(得分:0)

如果没有看到数据模式,我的猜测是GAMETIMENullable<DateTime> - 即映射到DB中的datetime / time字段可以为null。 Resharper只是给你一个静态分析警告,你引用Nullable<T>.Value而不检查它是否有值。

您可以这样重写查询:

var data = from d in dc.GAMEs
    where (d.GAMEDATE + (d.GAMETIME.HasValue ? d.GAMETIME.TimeOfDay : new TimeSpan())) >= DateTime.Now
        && d.GAMESTAT == 'O' && d.GAMETYPE == 0 select d;

GAMETIME为NULL时,上述查询将使用TimeSpan为0。

考虑到GAMEDATE是一个不可为空的数据库字段而GAMETIME是可以为空的,我建议您也使GAMETIME不可为空。这样两个字段是一致的,不需要额外的逻辑来处理NULL值。

编辑我刚刚确认,尝试拨打Nullable<T>.Value确实会引发InvalidOperationException,而不是NullReferenceException

来自horse's mouth(粗暴是我的):

  

这两个基本成员   可以为Nullable的结构是HasValue   和Value属性。如果是HasValue   Nullable对象的属性是   是的,对象的值可以是   使用Value属性访问。 如果   HasValue属性为false,即   对象的值是未定义的   试图访问价值   财产投掷   出现InvalidOperationException