Comparaciones de NULL
Un valor null en el origen de datos indica que el valor es desconocido. En las consultas de LINQ to Entities, puede comprobar si ha valores NULL para que ciertos cálculos o comparaciones sólo se realicen en las filas que tengan datos válidos, que no sean NULL. Sin embargo, la semántica de NULL de CLR puede diferir de la del origen de datos. La mayoría de las bases de datos utilizan una versión de lógica con tres valores para tratar las comparaciones de NULL. Es decir, una comparación con un valor NULL no se evalúa como true o false, se evalúa como unknown. A menudo ésta es una implementación de los valores NULL ANSI, pero este no es siempre el caso.
De forma predeterminada en SQL Server, al comparar si un valor NULL es igual a un valor NULL, se devuelve un valor NULL. En el ejemplo siguiente, las filas donde Region es NULL se excluyen del conjunto de resultados y la instrucción Transact-SQL devolvería 0 filas.
-- Find orders and customers with no regions.
SELECT a.[CustomerID]
FROM [Northwind].[dbo].[Customers] a
JOIN [Northwind].[dbo].[Orders] b ON a.Region = b.ShipRegion
WHERE a.Region IS Null
Esto es muy diferente de la semántica de NULL de CLR, donde la comparación de igualdad entre valores NULL devuelve true.
La consulta de LINQ siguiente se expresa en el CLR, pero se ejecuta en el origen de datos. Dado que no hay ninguna garantía de que la semántica de CLR se vaya a cumplir en el origen de datos, el comportamiento esperado es indeterminado.
Using NwEntities As New NorthwindEntities()
Dim customers As ObjectQuery(Of Customers) = NwEntities.Customers
Dim orders As ObjectQuery(Of Orders) = NwEntities.Orders
Dim query = _
From c In customers _
Join o In orders On c.Region Equals o.ShipRegion _
Where c.Region = Nothing _
Select c.CustomerID
For Each customerID In query
Console.WriteLine("Customer ID: ", customerID)
Next
End Using
using (NorthwindEntities NwEntities = new NorthwindEntities())
{
ObjectQuery<Customers> customers = NwEntities.Customers;
ObjectQuery<Orders> orders = NwEntities.Orders;
IQueryable<string> query = from c in customers
join o in orders on c.Region equals o.ShipRegion
where c.Region == null
select c.CustomerID;
foreach (string customerID in query)
{
Console.WriteLine("Customer ID: {0}", customerID);
}
}
Selectores de clave
Un selector de clave es una función utilizada en los operadores de consulta estándar para extraer una clave de un elemento. En la función de selector de clave, una expresión se puede comparar con una constante. La semántica de NULL del CLR se exhibe si una expresión se compara con una constante NULL o si se comparan dos constantes NULL. La semántica de NULL del almacén se exhibe si se comparan dos columnas con valores NULL del origen de datos. Los selectores de clave se encuentran en muchos de los operadores de consulta estándar de agrupamiento y ordenación, como GroupBy, y se utilizan para seleccionar las claves por las que ordenar o agrupar los resultados de una consulta.
Propiedad NULL en un objeto NULL
En el Entity Framework, las propiedades de un objeto NULL son NULL. Al intentar hacer referencia a una propiedad de un objeto NULL en el CLR, recibirá NullReferenceException. Cuando una consulta de LINQ implica una propiedad de un objeto NULL, puede provocarse un comportamiento incoherente.
Por ejemplo, en la consulta siguiente, la conversión a NewProduct
se efectúa en el nivel de árbol de comandos, que podría hacer que la propiedad Introduced
sea NULL. Si la base de datos definió las comparaciones de NULL de modo que la comparación de DateTime se evalúe como true, la fila se incluirá.
Using AWEntities As New AdventureWorksEntities()
Dim dt As DateTime = New DateTime()
Dim query = AWEntities.Product _
.Where(Function(p) _
((DirectCast(p, NewProduct)).Introduced > dt)) _
.Select(Function(x) x)
End Using
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
DateTime dt = new DateTime();
var query = AWEntities.Product
.Where(p => (p as NewProduct).Introduced > dt)
.Select(x => x);
}