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

Ternary operator inside a "Where" evaluates all elements even if it's not necessary #20496

Closed
taixes opened this issue Apr 2, 2020 · 4 comments
Labels
closed-no-further-action The issue is closed and no further action is planned. customer-reported

Comments

@taixes
Copy link

taixes commented Apr 2, 2020

If we have a ternary operator inside a Where:

var someBoolean = FunctionThatReturnsSomeBoolean();

this.Context
    .Elements
    .Where(e => someBoolean ? e.Id > 5 : true)
    .Any();

I'd expect that EF would evaluate the ternary before generating the SQL queries. Something like that:

var someBoolean = FunctionThatReturnsSomeBoolean();

if (someBoolean)
{
    this.Context
        .Elements
        .Where(e => e.Id)
        .Any();
}
else
{
    this.Context
        .Elements
        .Any();
}

This would makes queries simpler and, more important, would avoid bugs like the following one:

DateTime? nullableDateTime= FunctionThatReturnsSomeNullableDateTime();

this.Context
    .Elements
    .Where(e => nullableDateTime.HasValue ? e.Date > nullableDateTime.Value : true)
    .Any();

In that case, if nullableDateTime is null, nullableDateTime.Value should never be called, but I'm getting the exception:

InvalidOperationException: An exception was thrown while attempting to evaluate the LINQ query parameter expression.

Steps to reproduce

Elements is a table of the context with a Date column.

var date = (System.DateTime?)null;

var anyElement = this.Elements
	.Where(e => date.HasValue ? e.Date > date.Value : true)
        .AnyAsync();

Further technical details

EF Core version: .Net Core 3.1
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: (e.g. .NET Core 3.1)
Operating system: Windows 10
IDE: Visual Studio 2019 16.5.2

@smitpatel
Copy link
Contributor

Duplicate of #17942

@smitpatel smitpatel marked this as a duplicate of #17942 Apr 2, 2020
@taixes
Copy link
Author

taixes commented Apr 2, 2020

I see it's probably duplicate, sorry. I just wonder if the fix for the Select will work also for the Where. Probably it will...?

@smitpatel
Copy link
Contributor

I am not able to reproduce this on EF Core 3.1.0
I used following code.

public class Program
    {
        public static async Task Main(string[] args)
        {
            using (var db = new MyContext())
            {
                // Recreate database
                db.Database.EnsureDeleted();
                db.Database.EnsureCreated();

                // Seed database


                db.SaveChanges();
            }

            using (var db = new MyContext())
            {
                // Run queries
                var nullableDateTime = FunctionThatReturnsSomeNullableDateTime();
                var query = db.Blogs
                    .Where(b => nullableDateTime.HasValue ? b.Date > nullableDateTime.Value : true)
                    .ToList();
            }
            Console.WriteLine("Program finished.");
        }

        private static DateTime? FunctionThatReturnsSomeNullableDateTime() => null;
    }


    public class MyContext : DbContext
    {
        private static ILoggerFactory ContextLoggerFactory
            => LoggerFactory.Create(b =>
            {
                b
                .AddConsole()
                .AddFilter("", LogLevel.Debug);
            });

        // Declare DBSets
        public DbSet<Blog> Blogs { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            // Select 1 provider
            optionsBuilder
                .UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=_ModelApp;Trusted_Connection=True;Connect Timeout=5;ConnectRetryCount=0")
                //.UseSqlite("filename=_modelApp.db")
                //.UseInMemoryDatabase(databaseName: "_modelApp")
                //.UseCosmos("https://localhost:8081", @"C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==", "_ModelApp")
                .EnableSensitiveDataLogging()
                .UseLoggerFactory(ContextLoggerFactory);
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            // Configure model
        }
    }

    public class Blog
    {
        public int Id { get; set; }
        public DateTime Date { get; set; }
    }

Given that the issue was fixed in 3.1.0, please make sure that you are using latest release of EF Core.

@taixes
Copy link
Author

taixes commented Apr 3, 2020

I am working with 3.1 but I was doing this test in a different branch which was (I don't know why) in 3.0. I upgraded to 3.1 and problem solved. My bad, sorry for wasting your time.

@taixes taixes closed this as completed Apr 3, 2020
@smitpatel smitpatel added the closed-no-further-action The issue is closed and no further action is planned. label Apr 3, 2020
@ajcvickers ajcvickers reopened this Oct 16, 2022
@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Oct 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-no-further-action The issue is closed and no further action is planned. customer-reported
Projects
None yet
Development

No branches or pull requests

3 participants