HotChocolate 16 Migration

Trax.Api.GraphQL and its companion packages now build against HotChocolate 16. Most of the surface is unchanged, but HotChocolate 16 renamed several types, split its service containers, and renamed four scalars. This page lists what a consuming host has to change.

Update your HotChocolate references

Every HotChocolate package a host references must move to 16 in lockstep with Trax. Two package changes matter:

PackageChange
HotChocolate.ExecutionDiscontinued. Its types moved into HotChocolate.Execution.Abstractions, which HotChocolate already brings in. Delete the reference.
HotChocolate.Execution.ProjectionsNew. Trax.Api.GraphQL depends on it; reference it directly only if your own code calls AsSelector.

Renamed types

BeforeAfter
ISchemaISchemaDefinition
IObjectTypeIObjectTypeDefinition
IDirectiveCollectionIReadOnlyDirectiveCollection (and IDirective.Type.Name becomes IDirective.Definition.Name)
IOperationResultOperationResult
IRequestContextRequestContext
IDocumentValidatorContextDocumentValidatorContext
IRequestExecutorResolverIRequestExecutorProvider for lookups, IRequestExecutorManager when you also evict
resolver.GetRequestExecutorAsync(...)provider.GetExecutorAsync(...)
schema.GetType<T>(name)schema.Types.GetType<T>(name)

Schema components no longer see your application services

HotChocolate 16 builds request interceptors, socket-session interceptors, diagnostic listeners and error filters from a schema container that does not fall through to the application container. A component that takes IHttpContextAccessor, an options monitor, or any host registration now fails to activate with Unable to resolve service for type ....

Bridge each dependency across:

builder.AddApplicationService<IAuthenticationSchemeProvider>();
builder.AddHttpRequestInterceptor<MyInterceptor>();

The bridge resolves eagerly while the schema container is built, so bridging a service the host did not register turns an optional dependency into a startup failure. Bridge conditionally when the component itself is wired conditionally.

IServiceProvider and IServiceScopeFactory cannot be bridged: the schema container registers its own and those win. A component that resolves services dynamically takes TraxApplicationServices instead, which Trax registers and bridges for you.

public sealed class MySocketInterceptor(TraxApplicationServices applicationServices)
    : DefaultSocketSessionInterceptor
{
    // applicationServices.Services is the host container, with its scoped registrations.
}

Trax wires its own interceptors this way already. You only need it for components you register yourself.

connection_init payloads

IOperationMessagePayload.As<T>() is gone. Read the raw JSON instead:

var payload = init.Payload?.Deserialize<MyPayload>(
    new JsonSerializerOptions(JsonSerializerDefaults.Web)
);

Watch for a silent failure here: LanguageExt (a Trax dependency) supplies an unrelated As<T>() extension, so the old call still compiles and returns null at runtime. Search for .As< in your socket interceptors rather than trusting the compiler.

Scalar renames change your SDL

Four built-in scalars were renamed. Any entity property of these CLR types produces a different type name in the schema, which breaks generated clients until they are regenerated:

CLR typeBeforeAfter
TimeSpanTimeSpanDuration
UriURLURI
byteByteUnsignedByte
sbyteSignedByteByte

Trax's own admin schema exposes one of these (operations.dispatch.delay is a TimeSpan), so regenerate any client bound to it.

Server defaults that moved

SettingChange
BatchingOff by default. Enable with ModifyServerOptions(o => o.Batching = AllowedBatching.All).
Document and operation cachesSized through ModifyOptions(o => o.OperationDocumentCacheSize = ...) / PreparedOperationCacheSize, not AddDocumentCache() / AddOperationCache().
Schema initializationEager by default. Remove InitializeOnStartup(); opt out with ModifyOptions(o => o.LazyInitialization = true).
Parser limitsNew caps on recursion depth, directives per location, and fragment visits.
ConcurrencyNew MaxConcurrentExecutions (default 64).

Trax's own hardening defaults (execution depth, cost, per-request operation cap) are unchanged and still applied by AddTraxGraphQL.

Projection

[UseProjection] is deprecated upstream, and Trax no longer uses it: query-model fields project through HotChocolate's execution-time projection subsystem instead. The behaviour a caller sees is the same, with one improvement, which is that a hand-written [ExtendObjectType] resolver now receives the parent properties it needs. See query models.

If you previously worked around that with [IsProjected(true)] on an entity property, delete it. The key of a query model is now added automatically, and anything else is declared on the resolver with [Parent(requires: ...)], which is enforced by the architecture guards.

SDK Reference

AddTraxGraphQL | Query models | Cross-schema data loaders | Architecture guards