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

Accidentally using field instead of property for JSON metadata produce hard to understand exception #32939

Closed
joakimriedel opened this issue Jan 27, 2024 · 0 comments · Fixed by #32966
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 type-bug
Milestone

Comments

@joakimriedel
Copy link
Contributor

joakimriedel commented Jan 27, 2024

File a bug

I (ok Github Copilot ☺️) accidentially snuck in a field into a JSON metadata for a JSON column, instead of a proper property (get/set). This was during quite a large refactoring, so it took me quite some time before I spotted the error since the resulting exception did not point me in the right direction.

Could the DX be improved here please? Ideally there should be some error already when generating the migrations, but a more precise error thrown would help as well such as "The Baz field of Metadata should have been declared as a property with get/set".

Include your code

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

await using var context = new TestContext();

context.Database.EnsureDeleted();
context.Database.EnsureCreated();

// Index was out of range. Must be non-negative and less than the size of the collection.
var models = await context.BaseModels.ToListAsync();

public sealed class TestContext : DbContext
{
    public DbSet<TestModel> BaseModels => Set<TestModel>();

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        => optionsBuilder
            .UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFCoreJSONColumns;Integrated Security=True;TrustServerCertificate=true")
            .LogTo(Console.WriteLine, LogLevel.Information)
            .EnableSensitiveDataLogging();
    
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<TestModel>().OwnsOne(x => x.Json, b => b.ToJson());
    }
}

public class TestModel
{
    public int Id { get; set; }

    public class Metadata
    {
        // this works
        //public required TestEnum Baz { get; set; }

        // this doesn't
        public required TestEnum Baz;
    };

    public Metadata? Json { get; set; }
}

public enum TestEnum
{
    Foo = 1,
    Bar = 2
}

Include stack traces

Include the full exception message and stack trace for any exception you encounter.

Use triple-tick fences for stack traces. For example:

   at System.ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessException()
   at System.Collections.Generic.List`1.get_Item(Int32 index)
   at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.JsonEntityMaterializerRewriter.<VisitSwitch>g__GenerateJsonPropertyReadLoop|11_0(ParameterExpression managerVariable, ParameterExpression tokenTypeVariable, List`1 finalBlockVariables, List`1 valueBufferTryReadValueMethodsToProcess)
   at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.JsonEntityMaterializerRewriter.VisitSwitch(SwitchExpression switchExpression)
   at System.Linq.Expressions.ExpressionVisitor.VisitBinary(BinaryExpression node)
   at System.Dynamic.Utils.ExpressionVisitorUtils.VisitBlockExpressions(ExpressionVisitor visitor, BlockExpression block)
   at System.Linq.Expressions.ExpressionVisitor.VisitBlock(BlockExpression node)
   at System.Linq.Expressions.ExpressionVisitor.VisitConditional(ConditionalExpression node)
   at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.JsonEntityMaterializerRewriter.VisitConditional(ConditionalExpression conditionalExpression)
   at System.Linq.Expressions.ExpressionVisitor.VisitConditional(ConditionalExpression node)
   at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.JsonEntityMaterializerRewriter.VisitConditional(ConditionalExpression conditionalExpression)
   at System.Dynamic.Utils.ExpressionVisitorUtils.VisitBlockExpressions(ExpressionVisitor visitor, BlockExpression block)
   at System.Linq.Expressions.ExpressionVisitor.VisitBlock(BlockExpression node)
   at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.JsonEntityMaterializerRewriter.Rewrite(BlockExpression jsonEntityShaperMaterializer)
   at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.CreateJsonShapers(IEntityType entityType, Boolean nullable, ParameterExpression jsonReaderDataParameter, ParameterExpression keyValuesParameter, Expression parentEntityExpression, INavigation navigation)
   at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.VisitExtension(Expression extensionExpression)
   at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ProcessShaper(Expression shaperExpression, RelationalCommandCache& relationalCommandCache, IReadOnlyList`1& readerColumns, LambdaExpression& relatedDataLoaders, Int32& collectionId)
   at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.VisitShapedQuery(ShapedQueryExpression shapedQueryExpression)
   at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.VisitExtension(Expression extensionExpression)
   at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.VisitExtension(Expression extensionExpression)
   at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass12_0`1.<ExecuteAsync>b__0()
   at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetAsyncEnumerator(CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.System.Collections.Generic.IAsyncEnumerable<TEntity>.GetAsyncEnumerator(CancellationToken cancellationToken)
   at System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1.GetAsyncEnumerator()
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.<ToListAsync>d__67`1.MoveNext()
   at Program.<<Main>$>d__0.MoveNext() in D:\repos\EFCoreJSONColumns\Program.cs:line 9
   at Program.<<Main>$>d__0.MoveNext() in D:\repos\EFCoreJSONColumns\Program.cs:line 9

Include provider and version information

EF Core version: 8.0.1
Target framework: .NET 8.0

@maumar maumar self-assigned this Jan 27, 2024
maumar added a commit that referenced this issue Jan 31, 2024
… metadata produce hard to understand exception

When processing shaper for JSON streaming we didn't protect against the case where there are no properties on JSON entity that should be populated as part of the loop.
Fix check the count of properties we found before we start generating Switch-Case statement for PropertyName.

Fixes #32939
@maumar maumar added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Jan 31, 2024
@ajcvickers ajcvickers added this to the 9.0.0-preview2 milestone Jan 31, 2024
maumar added a commit that referenced this issue Feb 2, 2024
… metadata produce hard to understand exception

When processing shaper for JSON streaming we didn't protect against the case where there are no properties on JSON entity that should be populated as part of the loop.
Fix check the count of properties we found before we start generating Switch-Case statement for PropertyName.

Fixes #32939
maumar added a commit that referenced this issue Feb 2, 2024
… metadata produce hard to understand exception (#32966)

When processing shaper for JSON streaming we didn't protect against the case where there are no properties on JSON entity that should be populated as part of the loop.
Fix check the count of properties we found before we start generating Switch-Case statement for PropertyName.

Fixes #32939
roji pushed a commit to roji/efcore that referenced this issue Feb 9, 2024
…r JSON metadata produce hard to understand exception (dotnet#32966)

When processing shaper for JSON streaming we didn't protect against the case where there are no properties on JSON entity that should be populated as part of the loop.
Fix check the count of properties we found before we start generating Switch-Case statement for PropertyName.

Fixes dotnet#32939
@roji roji modified the milestones: 9.0.0-preview2, 9.0.0 Oct 12, 2024
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 type-bug
Projects
None yet
4 participants