GraphQL is not only a query language for API, but also a runtime to meet your data query. GraphQL provides an easy to understand and complete description of the data in your API, so that the client can accurately obtain the data it needs without any redundancy. It also makes it easier for the API to evolve over time and can be used to build powerful developer tools.
-- from https://graphql.cn
In the last blog post, our return value is a string. For most cases, we mostly return the json format of the entity class.
first edition
using HotChocolate;
using HotChocolate.Data;
using HotChocolate.Execution;
using HotChocolate.Types;
using System;
using System.Collections.Generic;
namespace GraphQLBase002
{
class Program
{
static void Main(string[] args)
{
FirstVersion.Run();
}
}
//Entity class
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
#region FirstVersion
public class FirstVersion
{
public static void Run()
{
var schema = SchemaBuilder.New()
.AddQueryType<QueryType>()
.Create();
var executor = schema.MakeExecutable();
//The return is a string, so the defined Resolver name is used to query
Console.WriteLine(executor.Execute("{ students }").ToJson());
}
public class Query
{
public IList<Student> GetStudents()
{
return new List<Student>() {
new Student {
Id = 100,
Name = "ABCD",
Age=20
},
new Student {
Id = 101,
Name = "EFGH",
Age=19
}
};
}
}
public class QueryType : ObjectType<Query>
{
protected override void Configure(IObjectTypeDescriptor<Query> descriptor)
{
//It is defined that there are students to request GetStudents method, and the return type is StringType, so the entity will be converted to Json in Resolver
descriptor.Field<Query>(t => t.GetStudents()).Name("students").Type<NonNullType<StringType>>().Resolver(ctx =>
{
var result = ctx.Parent<Query>().GetStudents();
return Newtonsoft.Json.JsonConvert.SerializeObject(result);
});
}
}
}
#endregion
In order to return a json, use Resolver to get GetStudents and turn the instance into a json. Because it is a string, the Type of this Field is StringType.
The running result looks like a json, not exactly a string in json format. In fact, it is very clear from our definition of Resolver; This is not what we want.
Second Edition
#region SecondVersion
public class SecondVersion
{
public static void Run()
{
var schema = SchemaBuilder.New()
.AddQueryType<QueryType>()
.Create();
var executor = schema.MakeExecutable();
Console.WriteLine(executor.Execute("{ student {id name} }").ToJson());
Console.WriteLine(executor.Execute("{ students {id name} }").ToJson());
}
public class Query
{
public Student GetStudent()
{
return new Student
{
Id = 1,
Name = "AAAAA",
Age = 19
};
}
public List<Student> GetStudents()
{
return new List<Student>{
new Student
{
Id = 100,
Name = "ABCD",
Age = 19
},
new Student
{
Id = 101,
Name = "EFGH",
Age = 20
}
};
}
}
public class StudentType : ObjectType<Student>
{
protected override void Configure(IObjectTypeDescriptor<Student> descriptor)
{
}
}
public class QueryType : ObjectType<Query>
{
protected override void Configure(IObjectTypeDescriptor<Query> descriptor)
{
descriptor.Field(t => t.GetStudent()).Type<NonNullType<StudentType>>().Name("student");
descriptor.Field(t => t.GetStudents()).Type<ListType<NonNullType<StudentType>>>().Name("students");
}
}
}
#endregion
This time, in order to stop being a json format string, we defined the type of StudentType in the code, telling the system that Student is not a simple type, but the attributes in Student are simple types, Therefore, there is no processing in Configure (if there is a custom complex type attribute in Student, this type must be further defined and processed in Configure). In QueryType, the type definition and renaming of two methods in Query are processed.
The operation results are as follows. Yes, this is the result we want; But I always feel that in order to return json, is our price a little high?
Third Edition
#region ThreeVersion
public class ThreeVersion
{
public static void Run()
{
var schema = SchemaBuilder.New()
.AddProjections()
.AddQueryType<Query>()
.Create();
var executor = schema.MakeExecutable();
Console.WriteLine(executor.Execute("{ student{id name age} }").ToJson());
Console.WriteLine(executor.Execute("{ students{id name age} }").ToJson());
}
public class Query
{
[UseProjection]
public Student GetStudent()
{
return new Student
{
Id = 1,
Name = "AAAAA",
Age = 19
};
}
[UseProjection]
public List<Student> GetStudents()
{
return new List<Student>{
new Student
{
Id = 100,
Name = "ABCD",
Age = 19
},
new Student
{
Id = 101,
Name = "EFGH",
Age = 20
}
};
}
}
}
#endregion
In this version, we use the chicken to lay eggs and use the UseProjection instead of the type we defined. Even the QueryType disappears. This kind of code is what we want. Let's pay more attention to the business logic rather than doing a lot of technical cooperation for GraphQL; In fact, from the second edition, we can see the defined types StudentType and QueryType. We also know that these types are very regular and can be replaced by code, that is, UseProjection.
The running result is the same as that of version 2.
