Skip to content

Switch expression missing brackets in generated code #227

Open

Description

@waiwaing

If a [Projectable] member has the form conditionA || x switch { ... }, Projectables translates it into:

conditionA || x == testValue ? value1 : value2

However, this is incorrect, as C# operator precedence means that this is effectively

(conditionA || x == testValue) ? value1 : value2

instead of the correct

conditionA || (x == testValue ? value1 : value2)

This presumably affects other operators with higher precedence as well, not just ||.

Full Repro
#:package EntityFrameworkCore.Projectables@6.0.6
#:package Microsoft.EntityFrameworkCore.Sqlite@10.0.2

#:property PublishAot=false
#:property EmitCompilerGeneratedFiles=true
#:property CompilerGeneratedFilesOutputPath=gen

using EntityFrameworkCore.Projectables;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;

using var connection = new SqliteConnection("Data Source=:memory:");
connection.Open();

using var context = new ReproContext(new DbContextOptionsBuilder<ReproContext>()
    .UseSqlite(connection)
    .UseProjectables()
    .Options);

context.Database.EnsureCreated();
context.Items.Add(new Item { Value = null, Flag = false });
context.SaveChanges();

const Mode mode = Mode.A;

Console.WriteLine(context.Items.Where(i => i.Matches(mode)).ToQueryString());
Console.WriteLine();
Console.WriteLine($"In memory: {new Item().Matches(mode)}, via EF: {context.Items.Count(i => i.Matches(mode))}");

public enum Mode { A, B }

public class Item
{
    public int Id { get; set; }
    public int? Value { get; set; }
    public bool Flag { get; set; }

    [Projectable]
    public bool Matches(Mode mode) => 
        Value == null || mode switch
        {
            Mode.A => Flag,
            _ => true,
        };
}

public class ReproContext(DbContextOptions<ReproContext> options) : DbContext(options)
{
    public DbSet<Item> Items => Set<Item>();
}

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions