EntityFramework.Filters
EntityFramework.Filters copied to clipboard
Nullable types and EntityFramework.Filters
EntityFramework 6.
The query:
var item = context.Items.FirstOrDefault(x => x.NullableProperty == filter.NullablePropertyValue);
Without EntityFramework.Filters it translates to:
...
WHERE (([Extent1].[NullableProperty] = @p__linq__0) OR (([Extent1].[NullableProperty] IS NULL) AND (@p__linq__0 IS NULL)))
After adding filter interceptor (both in DbConfiguration class or in OnModelCreating) the query is translated to:
...
WHERE ([Extent1].[NullableProperty] = @p__linq__0)
DBContext.Configuration.UseDatabaseNullSemantics = false; does not fix anything.
If your filter.NullablePropertyValue is not null, then
WHERE ([Extent1].[NullableProperty] = @p__linq__0)
its right.
But If your filter.NullablePropertyValue so the query should be just
WHERE (([Extent1].[NullableProperty] IS NULL) AND (@p__linq__0 IS NULL))
EF 6 has new default behavior - it translates queries for nullable types using this syntax:
WHERE (([Extent1].[NullableProperty] = @p__linq__0) OR (([Extent1].[NullableProperty] IS NULL) AND (@p__linq__0 IS NULL)))
After adding EntityFramework.Filters interceptor to the context this behavior is changed and queries are translated using old syntax i.e. EntityFramework.Filters messes up EntityFramework's behavior and produces unpredicted results.
The behavior of EF is controlled by configuration key DBContext.Configuration.UseDatabaseNullSemantics, but when EntityFramework.Filters interceptor is added this configuration does not change anything.
I had the same issue in my own extended filterung framework. It's a pretty simple change of the new EF versions > 6.0. They introduced a new property context.Configuration.UseDatabaseNullSemantics. The same property was introduced in the class DbQueryCommandTree, which must be created when filtering the base tree. To solve the issue you only have to change FilterInterceptor.cs:
.... interceptionContext.Result = new DbQueryCommandTree ( queryCommand.MetadataWorkspace, queryCommand.DataSpace, newQuery, validate: false, useDatabaseNullSemantics: interceptionContext.Result.UseDatabaseNullSemantics //otherwise we loose the setting ); ...
That's it :-)
I have fix localy by remplacing in FilterInterceptor.cs:
interceptionContext.Result = new DbQueryCommandTree( queryCommand.MetadataWorkspace, queryCommand.DataSpace, newQuery);
by
interceptionContext.Result = new DbQueryCommandTree( queryCommand.MetadataWorkspace, queryCommand.DataSpace, newQuery,true, context.Configuration.UseDatabaseNullSemantics);
If I have time, I fork and PR after work.