Comment résoudre le problème des dates nulles dans une requête linq ?

De ORSWiki
Aller à : navigation, rechercher

Imaginez que vous ayez besoin de calculer une date minimale dans une table :

   Dim dates = From d In context.MaTable Select d.MaDate
   Dim dDateMin = dates.Min

Tout se passe bien si la date est trouvée. Par contre, si aucune date n'est trouvée, par exemple avec un critère de recherche :

   Dim dates = From d In context.MaTable Where d.MaDate < #1/1/2017# Select d.MaDate
   Dim dDateMin = dates.Min

vous obtenez l'exception suivante :

   L'exception System.InvalidOperationException n'a pas été gérée
   HResult=-2146233079
   Message=Échec du cast en type valeur 'System.DateTime', car la valeur matérialisée est Null. Le paramètre générique du type de résultat ou la requête doit utiliser un type Nullable.
   Source=EntityFramework
   En anglais : The cast to value type 'System.DateTime' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.

Si vous cherchez sur le net une solution à ce problème, on vous propose toutes sortes de trucs inutiles alors que la solution est très simple : DefaultIfEmpty ! Cet opérateur vous donnera le constructeur par défaut du type recherché, ici une date minimale, et cette fois vous n'aurez pas d'exception levée, s'il n'y a pas d'enregistrement trouvé :

   Dim dDateMin = dates.DefaultIfEmpty.Min
   If dDateMin = Date.MinValue Then MsgBox("Vide !")

Même chose avec une simple liste :

   Dim lstDates = New List(Of Date) From {#1/1/2017#, #2/1/2017#}
   Dim dDateMin = lstDates.Min

Ok, mais :

   Dim lstDates2 = From d In lstDates Where d < #1/1/2017#
   Dim dDateMin2 = lstDates2.Min

provoque :

   L'exception System.InvalidOperationException n'a pas été gérée
   HResult=-2146233079
   Message=La séquence ne contient aucun élément.

Même solution :

   Dim dDateMin2 = lstDates2.DefaultIfEmpty.Min
   If dDateMin2 = Date.MinValue Then MsgBox("Vide !")