Skip to content

Commit

Permalink
Add complex id documentation (#6144)
Browse files Browse the repository at this point in the history
  • Loading branch information
PascalSenn authored May 12, 2023
1 parent a8a6682 commit 38c62d5
Showing 1 changed file with 74 additions and 0 deletions.
74 changes: 74 additions & 0 deletions website/src/docs/hotchocolate/v13/defining-a-schema/relay.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<Product>]
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<Query>()
// Add a type converter from string to your complex ID type
.AddTypeConverter<string, ProductId>(ProductId.Parse)
// Add a type converter back to string
.AddTypeConverter<ProductId, string>(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.
Expand Down

0 comments on commit 38c62d5

Please sign in to comment.