ChilliCream / ChilliCream/graphql-platform

Projections don't work for Marten nested objects

Open
#9,047 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

🌶️ hot chocolate Area: Projections
Dominant language
C#
Stars
5.8k
Forks
810
Avg merge
15h 39m
Merged PRs (30d)
98

Description

Product

Hot Chocolate

Version

15.1.12

Link to minimal reproduction

https://github.com/stef-bulteel/HCMartenBug

Steps to reproduce

Run the project
Test both queries in README.md

What is expected?

It is expected Projections "just work" per https://chillicream.com/docs/hotchocolate/v15/integrations/marten#projections

What is actually happening?

An error is thrown as soon as nested data is trying to be queried.
No actual query is launched against postgres.

Relevant log output
{
  "errors": [
    {
      "message": "Unexpected Execution Error",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "products"
      ],
      "extensions": {
        "message": "Value cannot be null. (Parameter 'key')",
        "stackTrace": "   at System.Collections.Generic.Dictionary`2.set_Item(TKey key, TValue value)\r\n   at Marten.Linq.Parsing.SelectParser.VisitConstant(ConstantExpression node) in /_/src/Marten/Linq/Parsing/SelectParser.cs:line 79\r\n   at Marten.Linq.Parsing.SelectParser.Visit(Expression node) in /_/src/Marten/Linq/Parsing/SelectParser.cs:line 34\r\n   at System.Linq.Expressions.ExpressionVisitor.VisitBinary(BinaryExpression node)\r\n   at Marten.Linq.Parsing.SelectParser.VisitBinary(BinaryExpression node) in /_/src/Marten/Linq/Parsing/SelectParser.cs:line 66\r\n   at Marten.Linq.Parsing.SelectParser.Visit(Expression node) in /_/src/Marten/Linq/Parsing/SelectParser.cs:line 34\r\n   at System.Linq.Expressions.ExpressionVisitor.VisitConditional(ConditionalExpression node)\r\n   at Marten.Linq.Parsing.SelectParser.Visit(Expression node) in /_/src/Marten/Linq/Parsing/SelectParser.cs:line 34\r\n   at Marten.Linq.Parsing.SelectParser.ReadBinding(MemberAssignment binding) in /_/src/Marten/Linq/Parsing/SelectParser.cs:line 116\r\n   at Marten.Linq.Parsing.SelectParser.VisitMemberInit(MemberInitExpression node) in /_/src/Marten/Linq/Parsing/SelectParser.cs:line 96\r\n   at Marten.Linq.Parsing.SelectParser.Visit(Expression node) in /_/src/Marten/Linq/Parsing/SelectParser.cs:line 34\r\n   at Marten.Linq.Parsing.SelectParser..ctor(ISerializer serializer, IQueryableMemberCollection members, Expression expression) in /_/src/Marten/Linq/Parsing/SelectParser.cs:line 27\r\n   at Marten.Linq.Parsing.SelectorVisitor.ToSelectTransform(Expression selectExpression, ISerializer serializer) in /_/src/Marten/Linq/Parsing/SelectorVisitor.cs:line 119\r\n   at Marten.Linq.Parsing.SelectorVisitor.VisitMemberInit(MemberInitExpression node) in /_/src/Marten/Linq/Parsing/SelectorVisitor.cs:line 78\r\n   at Marten.Linq.Parsing.SelectorVisitor.Visit(Expression node) in /_/src/Marten/Linq/Parsing/SelectorVisitor.cs:line 28\r\n   at Marten.Linq.CollectionUsage.BuildTopStatement(IMartenSession session, IQueryableMemberCollection collection, IDocumentStorage storage, QueryStatistics statistics) in /_/src/Marten/Linq/CollectionUsage.Compilation.cs:line 74\r\n   at Marten.Linq.Parsing.LinqQueryParser.BuildStatements() in /_/src/Marten/Linq/Parsing/LinqQueryParser.Statements.cs:line 33\r\n   at Marten.Linq.Parsing.LinqQueryParser.BuildHandler[TResult]() in /_/src/Marten/Linq/Parsing/LinqQueryParser.Handlers.cs:line 58\r\n   at Marten.Linq.MartenLinqQueryProvider.Execute[TResult](Expression expression) in /_/src/Marten/Linq/MartenLinqQueryProvider.cs:line 56\r\n   at Marten.Linq.MartenLinqQueryable`1.GetEnumerator() in /_/src/Marten/Linq/MartenLinqQueryable.cs:line 136\r\n   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)\r\n   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)\r\n   at HotChocolate.DefaultQueryableExecutable`1.<ToAsyncEnumerable>b__19_0()\r\n   at System.Threading.Tasks.Task`1.InnerInvoke()\r\n   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)\r\n--- End of stack trace from previous location ---\r\n   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)\r\n   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)\r\n--- End of stack trace from previous location ---\r\n   at HotChocolate.DefaultQueryableExecutable`1.ToAsyncEnumerable(CancellationToken cancellationToken)+MoveNext()\r\n   at HotChocolate.DefaultQueryableExecutable`1.ToAsyncEnumerable(CancellationToken cancellationToken)+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult()\r\n   at HotChocolate.Types.Pagination.QueryableCursorPagingHandler`1.QueryExecutor.QueryAsync(IQueryable`1 slicedQuery, IQueryable`1 originalQuery, Int32 offset, Boolean includeTotalCount, CancellationToken cancellationToken)\r\n   at HotChocolate.Types.Pagination.QueryableCursorPagingHandler`1.QueryExecutor.QueryAsync(IQueryable`1 slicedQuery, IQueryable`1 originalQuery, Int32 offset, Boolean includeTotalCount, CancellationToken cancellationToken)\r\n   at HotChocolate.Types.Pagination.CursorPagingHandler`2.SliceAsync(IResolverContext context, TQuery originalQuery, CursorPagingArguments arguments, CursorPaginationAlgorithm`2 algorithm, ICursorPaginationQueryExecutor`2 executor, CancellationToken cancellationToken)\r\n   at HotChocolate.Types.Pagination.QueryableCursorPagingHandler`1.SliceAsyncInternal(IResolverContext context, IQueryableExecutable`1 source, CursorPagingArguments arguments)\r\n   at HotChocolate.Types.Pagination.CursorPagingHandler.HotChocolate.Types.Pagination.IPagingHandler.SliceAsync(IResolverContext context, Object source)\r\n   at HotChocolate.Types.Pagination.PagingMiddleware.InvokeAsync(IMiddlewareContext context)\r\n   at HotChocolate.Execution.Processing.Tasks.ResolverTask.ExecuteResolverPipelineAsync(CancellationToken cancellationToken)\r\n   at HotChocolate.Execution.Processing.Tasks.ResolverTask.TryExecuteAsync(CancellationToken cancellationToken)"
      }
    }
  ],
  "data": {
    "products": null
  }
}
Additional context

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the linked minimal reproduction and run both queries described in its README. Trace the nested projection failure from the stack trace through the Marten SelectParser and Hot Chocolate projection execution, then verify that nested queries complete without the null-key error and that PostgreSQL receives the expected query.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, postgres
Domain
backend-api-design, databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.