I am building a small proof-of-concept project to see if we can use GrapQl on our services. The schema stitching feature looks really good and if we implement GraphQl, would really need it. After looking at the docs and running their example locally I felt confident enough to implement my own solution that mirrors more closely to our domain.
Here's the implementation:
// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<PeopleDbContext>(t=> t.UseInMemoryDatabase("PeopleDb"));
builder.Services.AddGraphQLServer()
.AddQueryType<PeopleQuery>()
.RegisterDbContext<PeopleDbContext>();
var app = builder.Build();
app.MapGraphQL();
app.Run();
// PeopleQuery.cs
public class PeopleQuery
{
public Person? GetPerson([FromServices] PeopleDbContext dbContext, int id) =>
dbContext.People.FirstOrDefault(t => t.Id == id);
}
// Person.cs
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime Birthdate { get; set; }
}
- Employees
// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<EmployeesDbContext>(t => t.UseInMemoryDatabase("EmployeesDb"));
builder.Services.AddHttpClient("people", t=> t.BaseAddress = new Uri("https://localhost:8080/graphql"));
builder.Services.AddHttpClient("companies", t=> t.BaseAddress = new Uri("https://localhost:9090/graphql"));
builder.Services.AddGraphQLServer()
.AddQueryType<EmployeesQuery>()
.AddRemoteSchema(SchemaNames.Companies,ignoreRootTypes:true)
.AddRemoteSchema(SchemaNames.Users, ignoreRootTypes:true)
.AddTypeExtensionsFromFile("./Stitching.graphql")
.RegisterDbContext<EmployeesDbContext>();
var app = builder.Build();
app.MapGraphQL();
app.Run();
// EmployeesQuery.cs
public class EmployeesQuery {
public Employee? GetEmployee([Service] HrDbContext dbContext, int id) =>
dbContext.Employees.FirstOrDefault(t=> t.Id == id);
}
// Employee.cs
public class Employee
{
public int Id { get; set; }
public int PersonId { get; set; }
public int CompanyId { get; set; }
}
// Stitching.graphql
extend type Employee {
person: Person @delegate(schema: "people", path: "person(id: $fields:personId)")
company: Company @delegate(schema: "companies", path: "company(id: $fields:companyId)")
}
- Companies
// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<CompanyDbContext>(t => t.UseInMemoryDatabase("CompanyDb"));
builder.Services.AddGraphQLServer()
.AddQueryType<CompaniesQuery>()
.RegisterDbContext<CompanyDbContext>();
var app = builder.Build();
app.MapGraphQL();
app.Run();
// CompaniesQuery.cs
public class CompaniesQuery
{
public Company? GetCompany([FromServices] CompanyDbContext dbContext, int id) =>
dbContext.Companies.FirstOrDefault(t=> t.Id == id);
}
// Company.cs
public class Company
{
public int Id { get; set; }
public string Name { get; set; }
public string CatchPhrase { get; set; }
}
All of this is using HotChocolate v12.14 and .NET 6.
If I run a simple query:
{
employee(id: 2) {
id
personId
person {
firstName
}
}
}
I get the following error, which means that I did not provide some variable:
"errors": [
{
"message": "Variable `__fields_personId` is required.",
"extensions": {
"code": "HC0018",
"variable": "__fields_personId",
"remote": {
"message": "Variable `__fields_personId` is required.",
"extensions": {
"code": "HC0018",
"variable": "__fields_personId"
}
},
"schemaName": "people"
}
}
]
As far as I understand, when I extend the type Employee
and I use $fields:personId
, it is referring to the field personId
in the instance of the Employee.
If in the file Stitching.graphql
I hardcode a value for the parameters (instead of the fields reference), the request is successful and it returns the expected result:
extend type Employee {
person: Person @delegate(schema: "people", path: "person(id: 1)")
company: Company @delegate(schema: "companies", path: "company(id: 1)")
}
I found this question but it has no replies.