diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs index 01dbeb99eb6..f9a975f47a0 100644 --- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs @@ -1822,19 +1822,35 @@ void ProcessFixup(IDictionary fixupMap) Empty())); } + var switchCases = new List(); var testsCount = testExpressions.Count; - var testExpression = IfThen( - testExpressions[testsCount - 1], - readExpressions[testsCount - 1]); - for (var i = testsCount - 2; i >= 0; i--) + // generate PropertyName switch-case code + if (testsCount > 0) { - testExpression = IfThenElse( - testExpressions[i], - readExpressions[i], - testExpression); + var testExpression = IfThen( + testExpressions[testsCount - 1], + readExpressions[testsCount - 1]); + + for (var i = testsCount - 2; i >= 0; i--) + { + testExpression = IfThenElse( + testExpressions[i], + readExpressions[i], + testExpression); + } + + switchCases.Add( + SwitchCase( + testExpression, + Constant(JsonTokenType.PropertyName))); } + switchCases.Add( + SwitchCase( + Break(breakLabel), + Constant(JsonTokenType.EndObject))); + var loopBody = Block( Assign(tokenTypeVariable, Call(managerVariable, Utf8JsonReaderManagerMoveNextMethod)), Switch( @@ -1842,12 +1858,7 @@ void ProcessFixup(IDictionary fixupMap) Block( Call(managerVariable, Utf8JsonReaderManagerSkipMethod), Default(typeof(void))), - SwitchCase( - testExpression, - Constant(JsonTokenType.PropertyName)), - SwitchCase( - Break(breakLabel), - Constant(JsonTokenType.EndObject)))); + switchCases.ToArray())); return (Loop(loopBody, breakLabel), propertyAssignmentMap); } diff --git a/test/EFCore.Relational.Specification.Tests/Query/AdHocJsonQueryTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/AdHocJsonQueryTestBase.cs index 755a97760fd..f9ee1bef0ab 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/AdHocJsonQueryTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/AdHocJsonQueryTestBase.cs @@ -266,6 +266,59 @@ public virtual async Task Missing_navigation_works_with_deduplication(bool async #endregion + #region 32939 + + [ConditionalFact] + public virtual async Task Project_json_with_no_properties() + { + var contextFactory = await InitializeAsync(seed: Seed30028); + using var context = contextFactory.CreateContext(); + context.Entities.ToList(); + } + + protected void Seed30028(Context32939 ctx) + { + var entity = new Context32939.Entity32939 + { + Empty = new Context32939.JsonEmpty32939(), + FieldOnly = new Context32939.JsonFieldOnly32939() + }; + + ctx.Entities.Add(entity); + ctx.SaveChanges(); + } + + protected class Context32939(DbContextOptions options) : DbContext(options) + { + public DbSet Entities { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity().Property(x => x.Id).ValueGeneratedNever(); + modelBuilder.Entity().OwnsOne(x => x.Empty, b => b.ToJson()); + modelBuilder.Entity().OwnsOne(x => x.FieldOnly, b => b.ToJson()); + } + + public class Entity32939 + { + public int Id { get; set; } + public JsonEmpty32939 Empty { get; set; } + public JsonFieldOnly32939 FieldOnly { get; set; } + + } + + public class JsonEmpty32939 + { + } + + public class JsonFieldOnly32939 + { + public int Field; + } + } + + #endregion + #region ArrayOfPrimitives [ConditionalTheory]