Comparaisons null
Une valeur null
dans la source de données indique que la valeur est inconnue. Dans les requêtes LINQ to Entities, vous pouvez vérifier les valeurs Null afin que certains calculs ou certaines comparaisons soient effectués uniquement sur les lignes qui ont des données valides, ou non Null. Toutefois, la sémantique Null CLR peut différer par rapport à la sémantique Null de la source de données. La plupart des bases de données utilisent une version de logique à trois valeurs pour gérer les comparaisons de valeurs Null. Autrement dit, une comparaison avec une valeur Null n'a pas la valeur true
ou false
; elle a la valeur unknown
. Il s'agit souvent d'une implémentation de valeurs ANSI Null, mais ce n'est pas toujours le cas.
Par défaut dans SQL Server, la comparaison Null-égale-Null retourne une valeur Null. Dans l'exemple suivant, les lignes dans lesquelles ShipDate
a la valeur Null sont exclues du jeu de résultats, et l'instruction Transact-SQL retournerait 0 ligne.
-- Find order details and orders with no ship date.
SELECT h.SalesOrderID
FROM Sales.SalesOrderHeader h
JOIN Sales.SalesOrderDetail o ON o.SalesOrderID = h.SalesOrderID
WHERE h.ShipDate IS Null
C'est très différent de la sémantique Null CLR, où la comparaison Null-égale-Null retourne true.
La requête LINQ suivante est exprimée dans le CLR, mais elle est exécutée dans la source de données. Étant donné que rien ne garantit que la sémantique CLR sera respectée au niveau de la source de données, le comportement attendu est indéterminé.
using (AdventureWorksEntities context = new AdventureWorksEntities())
{
ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders;
ObjectSet<SalesOrderDetail> details = context.SalesOrderDetails;
var query =
from order in orders
join detail in details
on order.SalesOrderID
equals detail.SalesOrderID
where order.ShipDate == null
select order.SalesOrderID;
foreach (var OrderID in query)
{
Console.WriteLine("OrderID : {0}", OrderID);
}
}
Using context As New AdventureWorksEntities()
Dim orders As ObjectSet(Of SalesOrderHeader) = context.SalesOrderHeaders
Dim details As ObjectSet(Of SalesOrderDetail) = context.SalesOrderDetails
Dim query = _
From order In orders _
Join detail In details _
On order.SalesOrderID _
Equals detail.SalesOrderID _
Where order.ShipDate = Nothing
Select order.SalesOrderID
For Each orderID In query
Console.WriteLine("OrderID: {0} ", orderID)
Next
End Using
Sélecteurs de clé
Un sélecteur de clé est une fonction utilisée dans les opérateurs de requête standard pour extraire une clé d'un élément. Dans la fonction du sélecteur de clé, une expression peut être comparée avec une constante. La sémantique Null CLR est exposée si une expression est comparée à une constante Null ou si deux constantes Null sont comparées. La sémantique Null du magasin est exposée si deux colonnes contenant des valeurs Null dans la source de données sont comparées. Les sélecteurs de clé, qui se trouvent dans un grand nombre des opérateurs de requête standard de classement et de regroupement, tels que GroupBy, sont utilisés pour sélectionner les clés sur lesquelles trier ou regrouper les résultats de la requête.
Propriété Null sur un objet Null
Dans Entity Framework, les propriétés d'un objet Null sont Null. Lorsque vous essayez de référencer une propriété d'un objet Null dans le CLR, vous recevez un objet NullReferenceException. Lorsqu'une requête LINQ implique une propriété d'un objet Null, cela peut provoquer un comportement incohérent.
Par exemple, dans la requête suivante, le cast en NewProduct
est effectué dans la couche de l’arborescence de commandes, ce qui peut rendre Null la propriété Introduced
. Si la base de données a défini des comparaisons de valeurs Null telles que la comparaison DateTime ait la valeur true, la ligne sera incluse.
using (AdventureWorksEntities context = new AdventureWorksEntities())
{
DateTime dt = new DateTime();
var query = context.Products
.Where(p => (p as NewProduct).Introduced > dt)
.Select(x => x);
}
Using context As New AdventureWorksEntities()
Dim dt As DateTime = New DateTime()
Dim query = context.Products _
.Where(Function(p) _
((DirectCast(p, NewProduct)).Introduced > dt)) _
.Select(Function(x) x)
End Using
Transmission de collections de valeurs Null aux fonctions d’agrégation
Dans LINQ to Entities, lorsque vous passez une collection qui prend en charge IQueryable
à une fonction d’agrégation, les opérations d’agrégation sont effectuées dans la base de données. Il peut y avoir des différences entre les résultats d'une requête qui a été effectuée en mémoire et ceux d'une requête qui a été effectuée dans la base de données. Avec une requête en mémoire, en l'absence de correspondance, la requête retourne zéro. Dans la base de données, la même requête retourne la valeur null
. Si une valeur null
est transmise à une fonction d'agrégation LINQ, une exception est levée. Pour accepter les éventuelles valeurs null
, transtypez les types et les propriétés des types qui reçoivent les résultats de la requête en types de valeur Nullable.