2010-07-15 60 views
1

我有一个LINQ2SQL查询,看起来像这样:这真的是一个可能的InvalidOperationException?

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#代码,引用值而不检查它是否有值会是这样,我不知道这是否是一个Linq查询是真的。

实际生成的SQL看起来非常可怕,并且让我想灼伤我的眼睛,但是我看不到任何看起来可能是空引用的东西。我可以放心地忽略这个吗?

(暂时忽略其他问题,如它返回预期的结果)

编辑:

在进一步的思考,我可以看到上面可能会导致异常的LinqToObjects查询,还有其他类型(XML?)。所以是的,我想Resharper只是在安全。

回答

2

当处理表达式树(如LINQ to SQL查询)时,它完全依赖于使用的LINQ提供程序(在您的情况下为LINQ to SQL)。因此,Resharper对您的查询说出任何有用的信息几乎是不可能的。我认为它只是将这些代码解释为正常的C#代表。我可以说忽略它是安全的,但也许会为下一个开发人员添加评论。

0

没有看到数据模式,我的猜测是GAMETIMENullable<DateTime> - 即映射到DB中可以为空的日期时间/时间字段。 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; 

上面的查询只需要使用的0时间跨度时GAMETIME为NULL。

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

编辑我刚才已经证实,试图调用Nullable<T>.Value确实抛出InvalidOperationException,不NullReferenceException

horse's mouth(粗体是矿):

的两个 可空结构的基本构件是的HasValue 和Value属性。如果Nullable对象的HasValue 属性为 为true,则可以使用Value属性访问该对象的值 。 如果 HasValue属性是false,则对象的 值是未定义和 访问Value 属性会引发 InvalidOperationException异常的尝试。

+0

我没有对数据库结构的控制权,它被第三方工具使用并且必须符合它们的模式。 FWIW,GAMEDATE也是可以空的,但没有必要访问任何成员,因为它是隐含的。另外,你的修改并不是真正的同一个查询,因为没有时间的gamedate只能在今天进行比较,而不是现在。 – 2010-07-15 21:11:10

+0

正确的是,与今天相比是后备。在你的表单中,当GAMETIME为NULL时,它就会崩溃。 – 2010-07-15 23:55:52