2010-07-15 5 views
1

J'ai une requête Linq2Sql qui ressemble à ceci:Est-ce vraiment une InvalidOperationException possible?

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 indiquent qu'il est « d.GAMETIME.Value.TimeOfDay » en bleu et en me disant qu'il est un possible System.InvalidOperationException. Bien que j'obtiens cela si c'était du code C#, référencer la valeur sans vérifier si elle a une valeur serait tel, je ne suis pas sûr que ce soit vrai pour une requête Linq.

Le réel SQL généré semble horrible, et me donne envie de brûler mes yeux, mais je ne vois rien qui ressemble à une référence nulle. Puis-je ignorer cela en toute sécurité?

(ignorer pour le moment les autres questions, comme si elle renvoie les résultats attendus)

EDIT:

Sur plus pensée, je peux voir comment le pourrait-dessus provoquer une exception dans une requête de LinqToObjects , et éventuellement d'autres types (XML?). Alors oui, je suppose que Resharper est en train d'être en sécurité.

Répondre

2

En traitant des arbres d'expression (comme cette requête LINQ to SQL) cela dépend totalement du fournisseur LINQ utilisé (dans votre cas LINQ to SQL). Par conséquent, il est (presque) impossible pour Resharper de dire quelque chose d'utile à propos de votre requête. Je pense qu'il interprète simplement ce code comme des délégués C# normaux. Je dirais qu'il est sûr d'ignorer, mais peut-être ajouter un commentaire pour le développeur suivant.

0

Sans voir le schéma de données, je suppose que GAMETIME est Nullable<DateTime> - c'est-à-dire mappé à un champ date/heure dans le DB qui peut être nul. Resharper vous donne simplement un avertissement d'analyse statique que vous référencez Nullable<T>.Value sans vérifier qu'il a une valeur.

Vous pouvez réécrire la requête de cette façon:

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; 

La requête ci-dessus il suffit d'utiliser un TimeSpan de 0 lorsque GAMETIME est NULL. Considérant que GAMEDATE est un champ de base de données non-nullable et GAMETIME est un nullable, je recommande que vous rendiez GAMETIME non-nullable aussi. De cette façon, les deux champs sont cohérents et n'ont pas besoin de logique supplémentaire pour gérer les valeurs NULL.

EDIT Je viens de confirmer que d'essayer d'appeler Nullable<T>.Value ne fait jeter InvalidOperationException, pas NullReferenceException.

De l'horse's mouth (bolding est à moi):

Les deux membres fondamentaux de la la structure Nullable sont les propriétés HasValue et valeur. Si la propriété HasValue pour un objet Nullable est true, la valeur de l'objet peut être accessible avec la propriété Value. Si la propriété HasValue est fausse, la valeur de l'objet est défini et une tentative d'accéder à la valeur propriété jette un InvalidOperationException.

+0

Je n'ai aucun contrôle sur la structure de la base de données, il est utilisé par un outil tiers et doit être conforme à leur schéma. FWIW, GAMEDATE est également nullable, mais il était inutile d'accéder à tous les membres, comme cela était implicite. Aussi, votre modification n'est pas vraiment la même requête puisqu'une gamedate sans un temps devrait être comparée à seulement aujourd'hui, pas maintenant. –

+0

Bon, par rapport à aujourd'hui, c'est le repli. Dans le formulaire que vous aviez, lorsque GAMETIME est NULL, il se bloque simplement. –

Questions connexes