Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect SQL translation for negated nullable boolean equality #35594

Closed
ixtreon opened this issue Feb 6, 2025 · 1 comment
Closed

Incorrect SQL translation for negated nullable boolean equality #35594

ixtreon opened this issue Feb 6, 2025 · 1 comment

Comments

@ixtreon
Copy link

ixtreon commented Feb 6, 2025

Description

According to C# null semantics, given a bool? A, the expressions !(A == true) and A != true should be equivalent. When used in a filter, both expressions should translate to SQL that includes rows where A is null. Previous versions of EF correctly reflected this behaviour. However, in v9, !(A == true) is incorrectly translated to SQL that excludes rows where A is null, while A != true is translated correctly.

This seems to apply to both the SQL Server and Sqlite providers.

Steps to reproduce

using Microsoft.EntityFrameworkCore;

var db = new MyContext();
var notBlocked = db.Set<User>().Where(x => !(x.IsBlocked == true)).ToQueryString();
var notBlocked2 = db.Set<User>().Where(x => x.IsBlocked != true).ToQueryString();

Console.WriteLine($"""
    Query 1:
    {notBlocked}

    Query 2:
    {notBlocked2}
    """);

class MyContext : DbContext
{
    public DbSet<User> Users { get; set; }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) 
        => optionsBuilder.UseSqlite();
}

class User
{
    public int Id { get; set; }
    public bool? IsBlocked { get; set; }
}

Expected Output

Using version 8.0.12 of EF and the Sqlite provider:

Query 1:
SELECT "u"."Id", "u"."IsBlocked"
FROM "Users" AS "u"
WHERE "u"."IsBlocked" = 0 OR "u"."IsBlocked" IS NULL

Query 2:
SELECT "u"."Id", "u"."IsBlocked"
FROM "Users" AS "u"
WHERE "u"."IsBlocked" <> 1 OR "u"."IsBlocked" IS NULL

Version 7.0.20 produces virtually the same output, only wrapping the IS NULL comparison in parentheses.

Actual Output

Using version 9.0.1 of EF and the Sqlite provider:

Query 1:
SELECT "u"."Id", "u"."IsBlocked"
FROM "Users" AS "u"
WHERE "u"."IsBlocked" = 0

Query 2:
SELECT "u"."Id", "u"."IsBlocked"
FROM "Users" AS "u"
WHERE "u"."IsBlocked" = 0 OR "u"."IsBlocked" IS NULL

Environment

EF Core version: 9.0.1
Database provider: Microsoft.EntityFrameworkCore.SqlServer, Microsoft.EntityFrameworkCore.Sqlite
Target framework: .NET 9.0
Operating system: Windows 11
IDE: Visual Studio 2022 17.12.3

@ixtreon ixtreon changed the title Incorrect SQL translation for nullable boolean inequality Incorrect SQL translation for negated nullable boolean equality Feb 6, 2025
@maumar
Copy link
Contributor

maumar commented Feb 7, 2025

This is a duplicate of #35393, which will be fixed in 9.0.3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants