efcore.pg icon indicating copy to clipboard operation
efcore.pg copied to clipboard

List Of List to JsonB .Net 8

Open zN3utr4l opened this issue 9 months ago • 7 comments

I'm migrating a .net 6 project to .net 8.

I have this entities:

public class Entity
{
    public List<List<SubEntity>>? SubEntities{ get; set; }
}

public class SubEntity
{
    public required string Key { get; set; }

    public required string Value { get; set; }
}

in .net 6 by setting HasColumnType('jsonb') everything is ok, now with .net 8 (https://www.npgsql.org/efcore/mapping/json.html#tojson-owned-entity-mapping) doing this:

public class EntityConfiguration : IEntityTypeConfiguration<Entity>
{
    public void Configure(EntityTypeBuilder<Entity> builder)
    {
        builder.OwnsMany(x => x.SubEntities, r => { r.ToJson(); });
    }
}

This error comes up: System.InvalidOperationException: Invalid token type: 'StartArray'.

2024-05-16 15:43:05.4282||ERROR|TrackMiddleware.cs|NLogAppender|Exception: System.InvalidOperationException: Invalid token type: 'StartArray'.
   at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.IncludeJsonEntityCollection[TIncludingEntity,TIncludedCollectionElement](QueryContext queryContext, Object[] keyPropertyValues, JsonReaderData jsonReaderData, TIncludingEntity entity, Func`4 innerShaper, Action`1 getOrCreateCollectionObject, Action`2 fixup, Boolean trackingQuery)
   at lambda_method718(Closure, QueryContext, DbDataReader, ResultContext, SingleQueryResultCoordinator)
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
   at System.Collections.Generic.List`1.AddRange(IEnumerable`1 collection)
   at MyProj.PostgreSQL.Repository.Entity.EntityRepository.GetTopFavoriteEntity(Int32 max) in G:\MyProj\MyProj.Cloud\MyProj.PostgreSQL\Repository\Entity\EntityRepository.cs:line 34
   at MyProj.Web.Controllers.DashboardController.Index() in G:\MyProj\MyProj.Cloud\MyProj.Web\Controllers\DashboardController.cs:line 23
   at lambda_method698(Closure, Object, Object[])
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|7_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at MyProj.Web.Middleware.TrackMiddleware.Invoke(HttpContext context, IUnitOfWork unitOfWork) in G:\MyProj\MyProj.Cloud\MyProj.Web\Middleware\TrackMiddleware.cs:line 67 StackTrace:    at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.IncludeJsonEntityCollection[TIncludingEntity,TIncludedCollectionElement](QueryContext queryContext, Object[] keyPropertyValues, JsonReaderData jsonReaderData, TIncludingEntity entity, Func`4 innerShaper, Action`1 getOrCreateCollectionObject, Action`2 fixup, Boolean trackingQuery)
   at lambda_method718(Closure, QueryContext, DbDataReader, ResultContext, SingleQueryResultCoordinator)
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
   at System.Collections.Generic.List`1.AddRange(IEnumerable`1 collection)
   at MyProj.PostgreSQL.Repository.Entity.EntityRepository.GetTopFavoriteEntity(Int32 max) in G:\MyProj\MyProj.Cloud\MyProj.PostgreSQL\Repository\Entity\EntityRepository.cs:line 34
   at MyProj.Web.Controllers.DashboardController.Index() in G:\MyProj\MyProj.Cloud\MyProj.Web\Controllers\DashboardController.cs:line 23
   at lambda_method698(Closure, Object, Object[])
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|7_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at MyProj.Web.Middleware.TrackMiddleware.Invoke(HttpContext context, IUnitOfWork unitOfWork) in G:\MyProj\MyProj.Cloud\MyProj.Web\Middleware\TrackMiddleware.cs:line 67 | G:\MyProj\MyProj.Cloud\MyProj.Web\Middleware\TrackMiddleware.cs:Invoke:127|

This is what the contents of the jsonb column look like when created with .net 6:

[
   [
      {
         "Key":"Test",
         "Value":"0"
      },
      {
         "Key":"Test2",
         "Value":"0"
      }
   ],
   [
      {
         "Key":"Test",
         "Value":"650"
      },
      {
         "Key":"Test2",
         "Value":"150"
      }
   ]
]

zN3utr4l avatar May 16 '24 14:05 zN3utr4l