-
Couldn't load subscription status.
- Fork 3.3k
Description
Since #36157, test NorthwindWhereQueryTestBase.Where_navigation_contains now fails when the default parameterized collection mode is set to ParameterizedCollectionMode.Parameter. The problem is that we have a special additional path creating InExpression with a value parameter, specifically for the case where Contains is invoked over the entity itself ("entity equality/containment"). The InExpression gets to SqlNullabilityProcessor, and then an UnreachableException gets thrown.
Ideally we'd remove this special path and deal with entity containment, but this presented some challenges back when I was re-implementing Contains so I left it out.
Note that before #36157 things were already hacky: because of the special path, we were expanding the value parameter to constants rather than using OPENJSON like everywhere else (see this baseline change). So I think it's OK if we continue to hack this a bit, and simply handle ParameterizedCollectionMode.Parameter in SqlNullabilityProcessor as if it's multiple parameters/constants.
Standalone repro
await using var context = new BlogContext();
await context.Database.EnsureDeletedAsync();
await context.Database.EnsureCreatedAsync();
List<BlogDetails> details = [new BlogDetails { Id = 1 }, new BlogDetails { Id = 2 }];
_ = await context.Blogs.Where(b => details.Contains(b.Details)).ToListAsync();
public class BlogContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseSqlServer("Server=localhost;Database=test;User=SA;Password=Abcd5678;Connect Timeout=60;ConnectRetryCount=0;Encrypt=false",
o => o.UseParameterizedCollectionMode(ParameterizedCollectionMode.Parameter))
.LogTo(Console.WriteLine, LogLevel.Information)
.EnableSensitiveDataLogging();
}
public class Blog
{
public int Id { get; set; }
public string Name { get; set; }
public BlogDetails Details { get; set; }
}
public class BlogDetails
{
public int Id { get; set; }
public string Name { get; set; }
}