Comment résoudre le problème des dates nulles dans une requête linq ?
De ORSWiki
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 !")