From 38c62d502fa7dd52d6ec8d143766ffd6f4b518c9 Mon Sep 17 00:00:00 2001 From: PascalSenn Date: Fri, 12 May 2023 10:36:08 +0200 Subject: [PATCH] Add complex id documentation (#6144) --- .../v13/defining-a-schema/relay.md | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/website/src/docs/hotchocolate/v13/defining-a-schema/relay.md b/website/src/docs/hotchocolate/v13/defining-a-schema/relay.md index f105ee755e5..83bf7698233 100644 --- a/website/src/docs/hotchocolate/v13/defining-a-schema/relay.md +++ b/website/src/docs/hotchocolate/v13/defining-a-schema/relay.md @@ -188,6 +188,80 @@ The `Serialize()` method takes the schema name as a first argument, followed by [Learn more about accessing services](/docs/hotchocolate/v13/fetching-data/resolvers#injecting-services) +# Complex Ids + +In certain situations, you may need to use complex identifiers for your data models, rather than simple integers or strings. HotChocolate provides support for complex IDs by allowing you to define custom ID types, which can be used in your GraphQL schema. + +## Defining Complex ID + +To define a complex ID, you need to create a new class or struct that will represent the complex ID, and use the `[ID]` attribute in the corresponding data model class. In this example, we will create a complex ID for a `Product` class. + +```csharp +public class Product +{ + [ID] // Define the ID on the type + public ProductId Id { get; set; } +} +``` + +### Using Type Extensions for Complex ID + +If your `Product` model does not have an ID field, but you still want to use a complex ID for GraphQL queries, you can use a type extension. + +A type extension allows you to add fields to a type that are only available within the GraphQL schema, without modifying the actual data model. +Here's how you can define the type extension: + +```csharp +[ExtendObjectType(typeof(Product))] +public class ProductExtensions +{ + // Define a method that will be used to compute the complex ID + [ID] + public ProductId GetId([Parent] Product product) + => new ProductId(product.SKU, product.BatchNumber); +} +``` + +This approach allows you to use complex IDs in your GraphQL schema without needing to modify your data models. It's particularly useful when working with databases that use **compound primary keys**, as it allows you to represent these keys as complex IDs in your GraphQL schema. + +## Creating Complex ID Structs + +Here's how you can define the `ProductId` struct: + +```csharp +public readonly record struct ProductId(string SKU, int BatchNumber) +{ + // Override ToString to provide a string representation for the complex ID + public override string ToString() => $"{SKU}:{BatchNumber}"; + + // Create a Parse method that converts a string representation back to the complex ID + public static ProductId Parse(string value) + { + var parts = value.Split(':'); + return new ProductId(parts[0], int.Parse(parts[1])); + } +} +``` + +This struct has a string `SKU` and an integer `BatchNumber` property, and can be converted to and from a string for easy usage in GraphQL queries. + +## Configuring Type Converters + +To integrate the `ProductId` struct into HotChocolate's type system, you need to define type converters. These converters enable HotChocolate to automatically transform between the `ProductId` struct and a string representation. + +```csharp +builder.Services.AddGraphQLServer() + .AddQueryType() + // Add a type converter from string to your complex ID type + .AddTypeConverter(ProductId.Parse) + // Add a type converter back to string + .AddTypeConverter(x => x.ToString()) + // Enable global object identification + .AddGlobalObjectIdentification(); +``` + +With these converters, you can now use `ProductId` as an ID in your GraphQL schema. When you receive a `ProductId` ID in a request, HotChocolate will automatically use the `ProductId.Parse` method to convert it into a `ProductId` object. Likewise, when returning a `ProductId` object in a response, HotChocolate will use the `ToString` method to convert it back into a string. + # Global Object Identification Global Object Identification, as the name suggests, is about being able to uniquely identify an object within our schema. Moreover, it allows consumers of our schema to refetch an object in a standardized way. This capability allows client applications, such as [Relay](https://relay.dev), to automatically refetch types.