Introducing GraphQLinq - Strongly Typed GraphQL Queries with LINQ to GraphQL.
Consuming a GraphQL api in C# is straightforward with either using HttpClient
directly or using a client library such as
GraphQL.Client but both suffer from the same problems: The GraphQL queries do not go through any compile-time checking, and any mistake in the query isn’t discovered until you execute the query at runtime. For example, to query
SpaceX GraphQL API for all missions where the manufacturer is Orbital ATK
you need to run the following query:
{
missions (find: {manufacturer: "Orbital ATK"}) {
id
name
description
twitter
website
wikipedia
manufacturers
}
}
.Net solved the same problem for SQL with LINQ: LINQ queries are first-class language objects and are strongly typed. This way, there are no hardcoded queries in the project, and the LINQ queries are type-checked by the compiler.
In this article, I will show how GraphQLinq - a LINQ to GraphQL library solves this problem.
Getting Started with GraphQLinq
GraphQLinq consists of two parts: GraphQLinq.Scaffolding
for generating strongly typed classes from the GrapQL endpoint and client library, GraphQLinq.Client
, for writing and executing LINQ to GraphQL queries.
GraphQLinq.Scaffolding
is a .NET tool, so run the following command to install it:
dotnet tool install --global --version 1.0.0-beta GraphQLinq.Scaffolding
This will install the tool globally and make it available for all projects.
Next, navigate to your project folder and run the graphql-scaffold
tool to scaffold the client-side code:
graphqlinq-scaffold https://api.spacex.land/graphql -o SpaceX -n SpaceX
This will generate the code in the SpaceX folder (specified by the o
option) and use SpaceX
as a namespace too.
Now, install the GraphQLinq.Client
package in your project to write some LINQ to GraphQL queries:
dotnet add package GraphQLinq.Client --version 1.0.0-beta
Running GraphQL Queries with LINQ
The scaffolding tool generates QueryContext
class that serves as an entry point for writing and running LINQ queries. For example, you can write the above graphQL query like this:
var spaceXContext = new QueryContext();
var missionsQuery = spaceXContext.Missions(new MissionsFind { Manufacturer = "Orbital ATK" }, null, null)
.Include(mission => mission.Manufacturers);
var missions = missionsQuery.ToList();
This LINQ query will generate a graphQL query that includes all primitive properties of the Mission
class and also includes the list of manufacturers in the query.
Here are a couple of more LINQ to GraphQL queries:
Query all Primitive Properties of a Type
Quering for all primitive properties is very straightforward:
var spaceXContext = new QueryContext();
var company = spaceXContext.Company().ToItem();
Query Specific Properties
var companySummary = spaceXContext.Company().Select(c => new CompanySummary
{
Ceo = c.Ceo,
Name = c.Name,
Headquarters = c.Headquarters
}).ToItem();
/// Alternatively, use an anonymous object
var companySummaryAnonymous = spaceXContext.Company().Select(c => new { c.Ceo, c.Name, c.Headquarters }).ToItem();
Include Navigation Properties
var companyWithHeadquartersAndLinks = spaceXContext.Company()
.Include(info => info.Headquarters)
.Include(info => info.Links).ToItem();
View Generated Query
To view the generated GraphQL query, call ToString
on the LINQ query itself. You will get the GraphQL query together with the variables bound to the query.
var missionsQuery = spaceXContext.Missions(new MissionsFind { Manufacturer = "Orbital ATK" }, null, null)
.Include(mission => mission.Manufacturers);
var query = missionsQuery.Query;
var fullQuery = missionsQuery.ToString();
After executing the above code snippet query
will be equal to:
query ($find: MissionsFind) { result: missions (find: $find) {
description
id
name
twitter
website
wikipedia
manufacturers
}}
and fullQuery
will be:
{"query":"query ($find: MissionsFind) { result: missions (find: $find) {
description
id
name
twitter
website
wikipedia
manufacturers
}}","variables":{"find":{"manufacturer":"Orbital ATK"}}}
Roadmap
The library is in the early stages and does not support all possible GraphQL schemas and queries. Check open issues for a list of proposed features and known issues.
If you find the library useful, don’t forget to ⭐ the GitHub repository. If you have any questions or suggestions, you are welcome to submit an issue or send a PR.