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

IQueryable.All evaluate to false with predicate _ => true #23617

Closed
tomek-anuszkiewicz opened this issue Dec 8, 2020 · 4 comments
Closed

IQueryable.All evaluate to false with predicate _ => true #23617

tomek-anuszkiewicz opened this issue Dec 8, 2020 · 4 comments
Assignees
Labels
area-query closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported regression Servicing-approved type-bug
Milestone

Comments

@tomek-anuszkiewicz
Copy link

IQueryable.All evaluate to false with predicate _ => true

With https://github.com/dotnet/EntityFramework.Docs/tree/master/samples/core/GetStarted
Modify Program.cs like:

using (var db = new BloggingContext())
{
    db.Database.Migrate();

    // Create
    Console.WriteLine("Inserting a new blog");
    db.Add(new Blog { Url = "http://blogs.msdn.com/adonet" });
    db.SaveChanges();

    if (db.Blogs.ToList().All(_ => true) != db.Blogs.All(_ => true))
        throw new Exception("Why?");
}

Shouldn't Blogs.All(_ => true) evaluate to true like db.Blogs.ToList().All(_ => true)?

EF Core version: 5
Database provider: Sqlite
Target framework: NET5
Operating system: Windows
IDE: VS2019

@ajcvickers
Copy link
Member

@tomek-anuszkiewicz I am not able to reproduce this. Copying that code into the GetStarted sample and running it does not generate an exception for me. Please attach a small, runnable project or post a small, runnable code listing that reproduces what you are seeing so that we can investigate.

@tomek-anuszkiewicz
Copy link
Author

tomek-anuszkiewicz commented Dec 14, 2020

I'm confused. On my home PC it works as you said. But on my company notebook for db.Blogs.All(_ => true); I get:

 SELECT 0

image

It also the same for Azure App Service because there where the error was spotted.

Sample project:
GetStarted - Copy.zip

@ajcvickers
Copy link
Member

Note for triage: this looks like a regression from 3.1 to 5.0. Logs from 3.1:

Inserting a new blog
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (2ms) [Parameters=[@p0='?' (Size = 28)], CommandType='Text', CommandTimeout='30']
      INSERT INTO "Blogs" ("Url")
      VALUES (@p0);
      SELECT "BlogId"
      FROM "Blogs"
      WHERE changes() = 1 AND "rowid" = last_insert_rowid();
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      SELECT "b"."BlogId", "b"."Url"
      FROM "Blogs" AS "b"
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      SELECT NOT EXISTS (
          SELECT 1
          FROM "Blogs" AS "b"
          WHERE 0 = 1)

Logs from 5.0:

Inserting a new blog
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (2ms) [Parameters=[@p0='?' (Size = 28)], CommandType='Text', CommandTimeout='30']
      INSERT INTO "Blogs" ("Url")
      VALUES (@p0);
      SELECT "BlogId"
      FROM "Blogs"
      WHERE changes() = 1 AND "rowid" = last_insert_rowid();
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      SELECT "b"."BlogId", "b"."Url"
      FROM "Blogs" AS "b"
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      SELECT 0
Unhandled exception. System.Exception: Why?
   at Program.Main() in /home/ajcvickers/Repros/GetStarted.-.Copy/GetStarted - Copy/Program.cs:line 25

Code:

class Program
    {
        static void Main()
        {
            using (var db = new BloggingContext())
            {
                db.Database.EnsureDeleted();
                db.Database.EnsureCreated();

                // Create
                Console.WriteLine("Inserting a new blog");
                db.Add(new Blog { Url = "http://blogs.msdn.com/adonet" });
                db.SaveChanges();

                var all = db.Blogs.ToList().All(_ => true);
                var all2 = db.Blogs.All(_ => true);
                
                if (all != all2)
                    throw new Exception("Why?");
            }
        }
    }

public class BloggingContext : DbContext
{
    private static ILoggerFactory ContextLoggerFactory
        => LoggerFactory.Create(b => b.AddConsole()); //.SetMinimumLevel(LogLevel.Information));

    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder options)
        => options
            .UseLoggerFactory(ContextLoggerFactory)
            .UseSqlite("Data Source=blogging.db");
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    public List<Post> Posts { get; } = new List<Post>();
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public int BlogId { get; set; }
    public Blog Blog { get; set; }
}

@smitpatel
Copy link
Contributor

@maumar - This could be some optimization which works on 0 = 1 in predicate and removes it. Can you investigate?

@ajcvickers ajcvickers added this to the 5.0.3 milestone Dec 18, 2020
maumar added a commit that referenced this issue Jan 5, 2021
…true

We have optimization for EXISTS, that returns false when the subquery has a predicate which filters out all the rows. In such case we return constant false. However, ExistExpression also stores information about it being negated or not (i.e. EXISTS vs NOT EXISTS).
If the Exists expression is negated and the predicate filters out all the rows we should return true instead.
maumar added a commit that referenced this issue Jan 5, 2021
…true

We have optimization for EXISTS, that returns false when the subquery has a predicate which filters out all the rows. In such case we return constant false. However, ExistExpression also stores information about it being negated or not (i.e. EXISTS vs NOT EXISTS).
If the Exists expression is negated and the predicate filters out all the rows we should return true instead.

Fixes #23617
maumar added a commit that referenced this issue Jan 5, 2021
…true

We have optimization for EXISTS, that returns false when the subquery has a predicate which filters out all the rows. In such case we return constant false. However, ExistExpression also stores information about it being negated or not (i.e. EXISTS vs NOT EXISTS).
If the Exists expression is negated and the predicate filters out all the rows we should return true instead.

Fixes #23617
@ajcvickers ajcvickers added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Jan 5, 2021
@maumar maumar removed this from the 5.0.3 milestone Jan 13, 2021
@ajcvickers ajcvickers reopened this Jan 27, 2021
@ajcvickers ajcvickers added this to the 5.0.3 milestone Jan 29, 2021
This was referenced Mar 15, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-query closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported regression Servicing-approved type-bug
Projects
None yet
Development

No branches or pull requests

4 participants