- Notifications
You must be signed in to change notification settings - Fork3
A wrapper library for GraphQL.NET that provides additional features to ease enterprise integration
License
Michannne/graphql-core
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
A wrapper library for GraphQL.NET that provides additional features to ease enterprise integration
GraphQL.NET can be foundhere
This library is licensed under theMIT License
The latest package can be downloaded through NuGet
PM> Install-Package GraphQL-Core
This library sits on top of GraphQL.NET to make it easier to integrate pre-existing C# models into a schema. A typical use case is providing a GraphQL interface as an alternative to a REST interface for a pre-existing API.
This library is designed with fluent API design to make it easy to maintain new GraphQL.NET configurations
The latest release supports the following features:
- Types
- Queries
- Query stitching
- Type stitching
- Auto-conversion of models to GraphQL type
- Auto-conversion of C# types to GraphQL type
- Lambda queries
- Mutations
- Unions
Supported C# types for auto-conversion:
- Any user model defined with
.Type<Model>()
- Any C# value-type
- Any class which implements
IEnumerable
,IList
orIQueryable
Instead of having to add several classes on top of pre-exising models, GraphQL-Core's main entrypoint --IGraphQLBuilder
, contains several features to ease integration of GraphQL.NET
User defined types can be added through the.Type<TModel>()
method:
services.AddGraphQL().Type<Books>().Type<Authors>().Build()
This will iterate through the properties on the Type and generate GraphQL Type-nodes for the class, containing proper fields.Notice the use of the.Build()
method on the last line. This is necessary to create the nodes, and allows classes that reference other classes to be automatically resolved to the corresponding GraphQL Type
Queries can be added through the.Query<TResult>()
method:
...after setting up the DataRepositoriesservices.AddGraphQL().Type<Books>().Type<Authors>().Query<List<Authors>>(()=>newQuery(){Expression="authors",Resolver=(context)=>authorRepo.GetAll()}).Build()
TheQuery
class supports all parameters that can be passed into theField
method from GraphQL.NET, including arguments:
services.AddGraphQL().Query<Author>(()=>newQuery(){Expression="author",Args=newQueryArguments(newQueryArgument(typeof(long).GetGraphTypeFromType(nullable:false)){Name="authorId",DefaultValue=0,Description="The Author to be searched"}),Resolver=(context)=>authorRepo.GetAll().Where(a=>a.AuthorId==(long)context.Arguments["authorId"])}).Build()
By default, GraphQL.NET does not support Query stitching, that is, chaining multiple queries in different files into one query. With GraphQL-Core, this behaviour is supported out-of-the-box:
IServiceProviderserviceProvider=services.BuildServiceProvider();services.AddSingleton<AuthorRepository>();services.AddSingleton<BookRepository>();AuthorRepositoryauthorRepo=serviceProvider.GetService<AuthorRepository>();BookRepositorybookRepo=serviceProvider.GetService<BookRepository>();services.AddGraphQL().Type<Books>().Type<Authors>().Query<List<Authors>>(()=>newQuery(){Expression="authors",Resolver=(context)=>authorRepo.GetAll()}).Query<List<Books>>(()=>newQuery(){Expression="books",Resolver=(context)=>bookRepo.GetAll()}).Build()
In this case,AddGraphQL()
returns an instance ofIGraphQLBuilder
, through which configurations can be chained. An alternative approach is to create seperate files to hold instances ofIGraphQLConfiguration
containing groups of types and queries.
publicclassLibraryConfiguration:IGraphQLConfiguration{publicAuthorRepositoryauthorRepo{get;set;}publicBookRepositorybookRepo{get;set;}publicLibraryConfiguration(AuthorRepository_authorRepo,BookRepository_bookRepo){authorRepo=_authorRepo;bookRepo=_bookRepo;}publicIGraphQLBuilderConfigure(IGraphQLBuilderbuilder)=>builder.Type<Books>.Type<Authors>.Query<List<Authors>>(()=>newQuery(){Expression="authors",Resolver=(context)=>authorRepo.GetAll()}).Query<List<Books>>(()=>newQuery(){Expression="books",Resolver=(context)=>bookRepo.GetAll()});}
With this approach,.Build()
should not be called, it will be called automatically by the.AddGraphQL()
middleware:
services.AddGraphQL((builer)=>(newLibraryConfiguration(authorRepo,booksRepo).Configure(builder)).(newAnotherConfiguration(myRepo).Configure(builder)) ...additional configurations can be chained here)
Type stitching is a useful feature that allows additional fields to be attached to a GraphQL Type node. GraphQL-Core makes this process very simple to do:
...after setting up the DataRepositoriesservices.AddGraphQL().Type<Books>().Type<Authors>().Stitch<Author,List<Books>>(expr:"books",joinOn: a=>a.AuthorIdjoinTo:()=>(id)=>(context)=>bookRepo.GetAll().Where(b=>b.AuthorId==(long)id)).Query<List<Authors>>(()=>newQuery(){Expression="authors",Resolver=(context)=>authorRepo.GetAll()}).Build()
TheAuthor
type will have a property namedbooks
which, when resolved, returns the list of books for that author. This is very useful in cases where an opaque user-defined model does not have an implied relationship with another user-defined type, and neither type can be changed to add a new property.
It should be noted this approach ismuch slower than a native join, such as.Include()
, whicn injects JOIN statements in the SQL queries sent to the database. As such, it is recommended to use this only if absolutely required for usability purposes, such as consumers of the GraphQL API that cannot view the database Ids in order to query theBooks
table seperately, and do not want to make two atomic calls to the API.
If you've noticed, nowhere is a seperate class being manually added to hold queries, mutations or types. This is because an internal class generator uses IL to create classes that act as containers for user-defined models at runtime. There are additional extension methods within the library that can convert C# types such asList<TModel>
intoListGraphType<GraphType<TModel>>
without intervention by the developer.
In addition, return types of queries can also be specifiec using C# types
About
A wrapper library for GraphQL.NET that provides additional features to ease enterprise integration