Exposing your XPO ORM using GraphQL

Note: you can download the full source code for this article in my GitHub repository 

In the past few years, I have been working on developing mobile applications, in the mobile world most of the applications will consume some type of data service, the main problem here is how to choose the correct data service? There are a lot of technologies to expose data over the wire and all of them are good somehow, so for me, the quest is about to find a technology where can I use my current skill set.

Today subject of study is GraphQL, an open source technology developed by Facebook that is a data query and manipulation language for API.

The beauty of GraphQL is its efficient and flexible approach to develop web APIs that can be queried to return a different data structure in the opposite side of the REST API and traditional web services that return a fix data structure, you can learn more about the GrahpQL project on their website https://graphql.org/

First, we will start by creating a new Asp.net core web application

A screenshot of a cell phone Description automatically generated

We name the application

A screenshot of a cell phone Description automatically generated

Then we select Empty for the project type

A screenshot of a cell phone Description automatically generated

Now that the project is created, we need to add a few NuGet packages, you can copy and paste the following snippet inside of your csproj file

<ItemGroup>

<PackageReference Include="DevExpress.Xpo" Version="18.2.7" />

<PackageReference Include="GraphQL" Version="2.4.0" />

<PackageReference Include="GraphQL.Server.Transports.AspNetCore" Version="3.4.0" />

<PackageReference Include="GraphQL.Server.Transports.WebSockets" Version="3.4.0" />

<PackageReference Include="Microsoft.AspNetCore.App" />

<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />

<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" />

<PackageReference Include="Microsoft.Data.Sqlite" Version="2.2.4" />

<PackageReference Include="System.Reactive" Version="4.1.5" />

</ItemGroup>

 

Now if let’s try to compile and run the application, at this moment you should see a “hello world” in your browser

A screenshot of a cell phone Description automatically generated

Now let’s add a second project to the solution to host the ORM, for that let’s use a NetStandard class library

A screenshot of a cell phone Description automatically generated

Let’s name the project XpoOrm, then edit the project file and add the following NuGet packages

<ItemGroup>

<PackageReference Include="DevExpress.Xpo" Version="18.2.7" />

<PackageReference Include="GraphQL" Version="2.4.0" />

<PackageReference Include="GraphQL.Server.Transports.AspNetCore" Version="3.4.0" />

<PackageReference Include="GraphQL.Server.Transports.WebSockets" Version="3.4.0" />

<PackageReference Include="System.Reactive" Version="4.1.5" />

</ItemGroup>

 

Now let’s add 3 folders, schema, services and models

A close up of a logo Description automatically generated

The basic structure of our project is ready, so let’s start adding some models, we will add 2 models products and categories, you can get the source of the files here

A screenshot of a cell phone Description automatically generated

A screenshot of a cell phone Description automatically generated

When you finish implementing the models the next step is to implement the services, remember that the main goal of GraphQL is to create a queryable layer between the client and the data service, you can architecture your service in the way that is more convenient for you but in this case I will create one service per entity, this services will be injected in our application using asp.net dependency injection. You can find the source for the services here

Product Service

A screenshot of a cell phone Description automatically generated

Category Service

A screenshot of a cell phone Description automatically generated

So far there we have not written any code related to GraphQL so now it’s the time. GraphQL does not directly expose your data model class instead it builds a type based on your model, let’s see how this will work for the Category model

A screenshot of a cell phone Description automatically generated

As you can see, I have created a new class that inherits from ObjectGraphType<T> where T is our XPO persistent class. Also, in the constructor I used the fluent API to map the fields from the category model to the CategoryType class, the method Field contains several overloads so you can do any type of crazy stuff in here, but for now I’m going keep it simple, now lets create the type for the product model.

A screenshot of a cell phone Description automatically generated

Now that we have created the ProductType class we can see that there are new characteristics here, the first new thing that you will notice is that in the constructor I injected the category service to load the category object related to the product, that is the common design pattern of GrahpQL, this approach is  useful if you are using POCO objects. Also, if you see the commented-out code you can see that when we use XPO we don’t need to inject the category service since it can be loaded directly from the instance of the Product class using XPO lazy loading feature. You can find both graph types here

Now that we have our graph types, we need to create 2 more classes, an object that will hold our list of queries and a schema object that will provide information about the types and the queries that we are exposing, let’s start with the queries object

A screenshot of a cell phone Description automatically generated

The Queries object is basically another graph type, but instead of exposing a model class is exposing the object class, it also uses the dependency injection to inject the 2 services that will forward the data to the fields. Now its time to create the schema for our GraphQL service

A screenshot of a cell phone Description automatically generated

A GraphQL schema can only expose one query so that is why I have created the object queries to hold all the possible subqueries of our services. As you can see, I injected the queries object and the dependency resolver, you can find the code for these classes here.

Now its time to go back to the asp.net core service and start the configuration of GrahpQL, let’s start with the program class

A screenshot of a cell phone Description automatically generated

As you can see in the main method there is some boilerplate code to initialize XPO data layer and create some sample data, nothing new if you are an XPO user you might be already familiar with this code. Now let’s move to the startup class

A screenshot of a cell phone Description automatically generated

As any asp.net core web application, there are 2 important methods let’s see what happened on each of them.

In the configure services method I register the services I created and the graph types also added the GraphQL service and the web sockets and data loader.

Now in the configure method I enabled the use of default files and static files, web sockets also I exposed the GrahpQL schema using web sockets and GrahpQL (this is the HTTP version of the API)

Our API is almost done, there is only one last step we need to do, we need a way to test our API for that we will use Graphical which is a web client to query GrahpQL APIs, the graphical project is hosted here https://github.com/graphql/graphiql but to make it simpler you can download the files from my GitHub repository here

Let’s create a wwwroot folder and add the graphical files into it

Run the application, you should see the graphical U.I and you should be able to navigate the API documentation

A screenshot of a social media post Description automatically generated

or you can query of XPO ORM

A screenshot of a social media post Description automatically generated

As you can see there is autocomplete on the query editor also we are able to query objects and nested objects on a field-based manner

This article is the first article on a series of how to expose any XPO ORM using GraphQL, in the next post we will learn about mutations