I have this LINQ query
dbContext.Customers.Where(c => c.AssetTag == assetTag).Count();
or
(from c in dbContext.Customers
That WHERE condition is generated this way because with ANSI NULLS setting, comparing AssetTag == null
will not return the corresponding rows in SQL (since in SQL world when comparing null to null the result is null). To keep the query behavior the same as a C# developer would expect, EF generates the extended WHERE clause. Note that previous versions of EF did not do so and thus did not work on databases with ANSI NULLS setting.
The GroupBy projection is there because EF supports much more complex queries before the .Count() call, such as joins, projections etc. This approach is thus more generic as it will work work all those scenarios as well.
In EF6 the database null semantics is the default comparison semantics. Note that this is a change to the default setting in EF5. In EF5 this flag was buried in ObjectContext.ContextOptions.UseCSharpNullComparisonBehavior and by default EF would use Linq to Object comparison semantics. In EF6 it is exposed on DbContext as DbContext.Configuration.UseDatabaseNullSemantics. You can find more details here
in C# string equivalency, null == null
evaluates to True
. null == null
in the database evaluates to False
. The script is verifying that either both the column value and the parameter are null, or that both are not null and they have the same string value.
WHERE
(
-- neither the column nor the paramter are null and
-- the column and the parameter have the same string value
([Extent1].[AssetTag] = @p__linq__0) AND
( NOT ([Extent1].[AssetTag] IS NULL OR @p__linq__0 IS NULL))
)
OR
(
-- both the column value and the parameter are null
([Extent1].[AssetTag] IS NULL) AND
(@p__linq__0 IS NULL)
)
For one thing, in C# c.AssetTag == assetTag
would be true if both are null. In SQL however, null compared to anything is always false. Therefore, if we want to generate a query that follows C# comparison mechanics, we must add additional conditions to ensure null compares evaluate to true if both are null:
([Extent1].[AssetTag] IS NULL) AND (@p__linq__0 IS NULL)