graphql-platform
graphql-platform copied to clipboard
Fix breaking change to `IResolverContext.Selection` in HotChocolate v14+ impacting classic projection
I came across this when trying to upgrade from v13 to v14 and then to v15. We use [UseMutationConvention] in tandem with [UseProjection] to refetch the entity being returned from database:
[UseMutationConvention(InputTypeName = nameof(BookInput))]
[UseProjection]
public async Task<Callsign?> AddBookAsync(
BookInput input,
IResolverContext context,
BookContext bookContext,
CancellationToken cancellationToken = default
)
{
var book = new Book(input.Name);
await bookContext.Books.AddAsync(book, cancellationToken);
await bookContext.SaveChangesAsync(cancellationToken);
var result = await bookContext.Books
.Where(it => it.ID == book.ID)
.Project(context)
.FirstOrDefaultAsync(cancellationToken);
return result;
}
We are excited about the new projection engine in v15 but are taking a lift and shift approach first, and I understand the classic projection engine is not considered deprecated in v15.
Debugging reveals that it seems context.Selection has had a rewrite and thus impacting QueryableProjectionProvider.cs which calls context.Selection.Type.UnwrapRuntimeType(). Whereas context.Selection.Type.UnwrapRuntimeType() would return Book in this case in v13, since v14 it has returned System.Object. This ultimately led to an exception being thrown:
Unable to cast object of type 'System.Linq.Expressions.Expression1`1[System.Func`2[System.Object,System.Object]]' to type 'System.Linq.Expressions.Expression`1[System.Func`2[Bookshop.Book,Bookshop.Book]]'.
at HotChocolate.Data.Projections.Expressions.QueryableProjectionScopeExtensions.Project[T](QueryableProjectionScope scope)
at HotChocolate.Data.Projections.Expressions.QueryableProjectionContextExtensions.Project[T](QueryableProjectionContext context)
at HotChocolate.Data.Projections.Expressions.QueryableProjectionProvider.<CreateApplicator>b__7_0[TEntityType](IResolverContext context, Object input)
at HotChocolate.Data.QueryableProjectExtensions.ExecuteProject[T](T input, IResolverContext context, Type expectedType)
at HotChocolate.Data.QueryableProjectExtensions.Project[T](IQueryable`1 queryable, IResolverContext context)
I understand it has been a few years since the maintainers have touched this part of HotChocolate. We are short on time but happy to file a bug report with minimal reproduction if that is the expectation before this PR can be considered.
@francisphn can you provide a test for this that would fail if this fix is not done?
I have moved this to the next patch release.