views:

29

answers:

2

I have a Linq2Sql query that looks like this:

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 is underlining the "d.GAMETIME.Value.TimeOfDay" in blue and telling me it's a possible System.InvalidOperationException. While I get that if it were C# code, referencing Value without checking if it has a value would be such, i'm not sure if that is true of a Linq query.

The actual SQL generated looks horrendous, and makes me want to burn my eyes out, but I see nothing that looks like it could be a null reference. Can I safely ignore this?

(ignore for the moment the other issues, such as if it returns the expected results)

EDIT:

Upon further thought, I can see how the above might cause an exception in a LinqToObjects query, and possibly other kinds (XML?). So yeah, I suppose Resharper is just being safe.

+1  A: 

When dealing with expression trees (as this LINQ to SQL query) it totally depends on the LINQ provider used (in your case LINQ to SQL). Therefore, it is (almost) impossible for Resharper to say anything useful about your query. I think it just interprets this code as normal C# delegates. I would say it is safe to ignore, but perhaps add a comment for the next developer.

Steven
A: 

Without seeing the data schema my guess is that GAMETIME is Nullable<DateTime> - i.e. maps to datetime/time field in the DB that can be null. Resharper is simply giving you a static analysis warning that you are referencing Nullable<T>.Value without checking that it has a value.

You can rewrite the query in this way:

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;

The above query will just use a TimeSpan of 0 when GAMETIME is NULL.

Considering that GAMEDATE is a non-nullable database field and GAMETIME is a nullable one, I recommend that you make GAMETIME non-nullable too. This way the two fields are consistent and do not need extra logic to handle NULL values.

EDIT I have just confirmed that trying to call Nullable<T>.Value does indeed throw InvalidOperationException, not NullReferenceException.

From the horse's mouth (bolding is mine):

The two fundamental members of the Nullable structure are the HasValue and Value properties. If the HasValue property for a Nullable object is true, the value of the object can be accessed with the Value property. If the HasValue property is false, the value of the object is undefined and an attempt to access the Value property throws an InvalidOperationException.

Igor Zevaka
I do not have control over the structure of the database, it's used by a third party tool and must conform to their schema. FWIW, GAMEDATE is also nullable, but it was unnecessary to access any members, as it was implied. Also, your modification isn't really the same query since a gamedate without a time would have to be compared to only today, not now.
Mystere Man
Right, comparing to today is the fallback. In the form you had it, when GAMETIME is NULL, it would simply crash.
Igor Zevaka