Skip to content

Projection is not working for nested objects #8603

@vvitkovsky

Description

@vvitkovsky

Product

Hot Chocolate

Version

15

Link to minimal reproduction

https://drive.google.com/file/d/1YPaavAY69gVCTe8-06i1eGjwGmD_paog/view?usp=drive_link

Steps to reproduce

Hello,

I've got an issue, that the projection is not working for complex types. I have those models:

public class Person
{
    public string Id { get; set; } = Guid.NewGuid().ToString();

    public int Version { get; set; } = 1;

    public string FirstName { get; set; } = null!;

    public string? LastName { get; set; }

    public int Age { get; set; }    

    public Address Address { get; set; } = null!; 
}

public class Address
{
    public string ZipCode { get; set; } = null!;
}

And I am using MongoDB over Entity Framework and query with pagination, projection, sorting, and filtering:

public class Query
{
    [UsePaging]
    [UseProjection]
    [UseSorting]
    [UseFiltering]    
    public IQueryable<Person> GetPersons([Service] PersonContext aContext)
    {
        return aContext.Persons.AsQueryable();
    }
}

When I perform a simple query, it works fine:

query {
  persons {
    nodes {
      id            
    }
  }
}

But when I add a nested object, it fails:

query {
  persons {
    nodes {
      id      
      address {
        zipCode
      }
    }
  }
}

Error is this one:

{
  "errors": [
    {
      "message": "Unexpected Execution Error",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "persons"
      ],
      "extensions": {
        "message": "A tracking query is attempting to project an owned entity without a corresponding owner in its result, but owned entities cannot be tracked without their owner. Either include the owner entity in the result or make the query non-tracking using 'AsNoTracking'.",
        "stackTrace": "   at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.EntityMaterializerInjectingExpressionVisitor.Inject(Expression expression)\r\n   at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.InjectEntityMaterializers(Expression expression)\r\n   at MongoDB.EntityFrameworkCore.Query.Visitors.MongoShapedQueryCompilingExpressionVisitor.VisitShapedQuery(ShapedQueryExpression shapedQueryExpression)\r\n   at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.VisitExtension(Expression extensionExpression)\r\n   at MongoDB.EntityFrameworkCore.Query.MongoQueryCompilationContext.CreateQueryExecutor[TResult](Expression originalQuery)\r\n   at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)\r\n   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)\r\n   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass11_0`1.<ExecuteCore>b__0()\r\n   at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)\r\n   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteCore[TResult](Expression query, Boolean async, CancellationToken cancellationToken)\r\n   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)\r\n   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)\r\n   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetAsyncEnumerator(CancellationToken cancellationToken)\r\n   at System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1.GetAsyncEnumerator()\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": {
    "persons": null
  }
}

I tried to modify a query like this:

aContext.Persons.AsQueryable().AsNoTracking();

But this didn't help.

Without [UseProjection], it works fine. Sample link attached.

Best regards,
Victor

What is expected?

[UseProjection] works for nested types

What is actually happening?

Projection is not working for nested types

Relevant log output

Additional context

No response

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions