Moving REST To GraphQL  With Asp.net Core & Entity Framework Core.

Moving REST To GraphQL With Asp.net Core & Entity Framework Core.

GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.

source: GraphQl

GraphQL queries are used to query the GraphQL server for the data that the client needs. What is interesting about GraphQL is that clients can write custom made queries based on the individual client’s needs. This means that GraphQL enables the client to ask for exactly what they want using a query and also returns a response with only what was asked. This approach gives the client more power.

Benefits of GraphQL:

  • Good fit for complex systems and microservices: By integrating multiple systems behind its API, GraphQL unifies them and hides their complexity. The GraphQL server is then responsible for fetching the data from the existing systems and packaging it up in the GraphQL response format.
  • Fetch data in single call and avoid multiple round trips:GraphQl is less chatty than Rest and rest api’s required multiple round trips between client and resources to fetch the data and return back to client to render on calling apps.

GraphQL solves the roundtrip problem by allowing the client to create a single query which calls several related functions (or resolvers) on the server to construct a response with multiple resources – in a single request. This is a much more efficient method of data delivery requiring fewer resources than multiple roundtrips.

  • Avoid Over/Under data fetching problems:REST api responses are known for either containing too much data or not enough of it, it’s very hard to design an API flexible enough to fulfill every client’s precise data needs. GraphQL solves this efficiency problem by fetching the exact data in a single request.

Building a GraphQL Service in ASP.NET Core

  1. Installing GraphQL in .net core: Since GraphQL support is not provided within ASP.NET Core, you need a Nuget package. Below are the most commonly used nuget packages used in .net core.
1
2
3

2. Setting up graph types: GraphTypes is a Class which derives from the ObjectGraphType base class that implements IObjectGraphType. Now in the constructor you can declare fields for this graph type. 

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using GraphQL;
using GraphQL.Types;
using WebApiWithGraphQl.Data.Entities;
using WebApiWithGraphQl.Repositories;

namespace WebApiWithGraphQl.GraphQ.Types
{
public class EmployeType : ObjectGraphType<Employee>
{
public EmployeType(EmployeeRepository employeeRepository)
{
Field(x => x.EmployeId);
Field(x => x.Name);
Field<EmployeeTypeEnumType>("EmploymentType", resolve: context => context.Source.EmployeType.ToString());

Field<ListGraphType<AddressType>>(

"Address",
resolve: context => employeeRepository.GetAdddressById(context.Source.EmployeId)
);
}
}
}

3. Define Resolver:Now that we have a Employe graph type we need another class that knows how to get Employees. I call it EmployeQuery which also derives from ObjectGraphType.
In the constructor I declare one field, this time I explicitly say that this field must return a list of EmployeType objects. As you can see even list is a special graph type.
Then I give the field a name and in a lambda I can now specify where the data should come from, in other words how to data should be resolved.

Resolvers are the functions responsible for supplying the data requested by the query and is the integration point between our application’s data source and the GraphQL infrastructure.

namespace WebApiWithGraphQl.GraphQ.Query
{
public class EmployeeQuery:ObjectGraphType
{
public EmployeeQuery(EmployeeRepository employeeRepository)
{
Field(
"Employees",
resolve: context => employeeRepository.GetAllEmployees()
);
}
}
}

2. Set up schema: A GraphQL schema is at the center of any GraphQL server implementation and describes the functionality available to the clients which connect to it.

GraphQL implements a human-readable schema syntax known as its Schema Definition Language, or “SDL”. The SDL is used to express the types available within a schema and how those types relate to each other. 

using GraphQL;
using GraphQL.Types;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WebApiWithGraphQl.GraphQ.Query;

namespace WebApiWithGraphQl.GraphQl
{
public class EmployeSchema :Schema
{
public EmployeSchema(IDependencyResolver resolver ):base(resolver)
{
Query = resolver.Resolve();
}
}
}

Configuring Asp.net Core With GraphQL Middleware

To setup GraphQL in your project and start using the scheme we created go to the startup class of your application.

  • Add the dependency resolver to get the query instance.
  • AddGraphQL extension method to register all the types GraphQL .NET uses
  • AddGraphTypes which will scan the assembly for all ObjectGraphTypes and register them automatically in the container using the specified lifetime.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext(options => options.UseSqlServer(Configuration.GetConnectionString("EmpoyeeDBConnectionString")));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info { Title = "My API", Version = "v1" });
});
services.AddScoped(s => new FuncDependencyResolver(s.GetRequiredService));
services.AddScoped();
services.AddScoped();

services.AddGraphQL(o => { o.ExposeExceptions = false; })
.AddGraphTypes(ServiceLifetime.Scoped);
}

Now we have to inject graphQL middleware by calling UseGraphQL extension method in configure method of startup.cs class.

public void Configure(IApplicationBuilder app, IHostingEnvironment env,EmployeeContext context)
{
app.UseGraphQL();
app.UseGraphQLPlayground(new GraphQLPlaygroundOptions());
context.Seed();

app.UseHttpsRedirection();
app.UseMvc();
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "API with graphQl V1");
});

}

Till now we have setup all the mandatory steps for graphQL integration with asp.net core api.If you want to see the playground UI as soon as you start the API go to the properties of the project and select the debug tab. Activate launch browser there and type in ui/playground as the url.

5

When the browser opens take a look at the schema tab on the right side. The metadata of the schema has been read by the playground.
Using this metadata information the query editor can have intellisense.
Type the query in the pic. It gets all products but only the names and descriptions. When I execute it you can see that the result is JSON and the data is contained in the data root node which has a products array with the data I asked for.

6
PlaygroundQueryExecution

Lazy Loading vs. Eager Loading

Download complete project : LazyLoadingEagerLoading.zip

The Entity Framework offers several different ways to load the entities that are related to your target entity. For example, when you query for Employee, there are different ways that the related Employee Addresses will be loaded into the Object State Manager. From a performance standpoint, the biggest question to consider when loading related entities will be whether to use Lazy Loading or Eager Loading.

When using Eager Loading, the related entities are loaded along with your target entity set. You use an Include statement in your query to indicate which related entities you want to bring in.

  • Lazy Loading – “don’t do the work until you absolutely have to.”

When using Lazy Loading, your initial query only brings in the target entity set. But whenever you access a navigation property, another query is issued against the store to load the related entity that means Related/child objects are not loaded automatically when a navigation property is accessed.Once an entity has been loaded, any further queries for the entity will load it directly from the Object State Manager. you can also turn off lazy loading for a particular property or an entire context. To turn off lazy loading for a particular property, do not make it virtual. To turn off lazy loading for all entities in the context, set its configuration property to false:

this.Configuration.LazyLoadingEnabled = false;

Rules for lazy loading:
  1. context.Configuration.ProxyCreationEnabled should be true.
  2. context.Configuration.LazyLoadingEnabled should be true.
  3. Navigation property should be defined as public, virtual. Context will NOT do lazy loading if the property is not defined as virtual.

Let’s start with actual implementation.Create Console Application with name LazyEagerLoading.

Lazy Loading

Step 1: Create Poco classes for employee and employeeAddress. PocoClassesaddresses Step 2: Create EmployeeContext and EmployeeDbInitilizer classes. Dbcontext DbInitilizer Step 3: As per the above code, i am trying to get employee details using the employeecontext class and then iterate through the employee item also try to read navigation property EmployeeAddresses. If you try to debug the code and find  that details for parent and child related tables comes at one time but this is not correct.Actually some thing different activity happens at back end and there are several sql query executed to get the details and to track this activity  i have used  sql profiler. you can see code for lazy loading and outcome of the code: LPLazyOutput

 

Now run the application. In the code above, note the first for-each loop, the data of only the main entity, the Employee, is loaded but not that of the EmployeeAddresses. The data of the related entity is loaded when the nested foreach loop is executed. Analysis report of sql profiler for above code execution: LazyProfiler Here you can see that there are four different queries executed to fetch the details from the database. first query executed to get employee details and other three queries executed to fetch the details of navigation property that is EmployeeAddress.This means that to fetch the data of the related entity, database calls are being made again and again, after the data for main entity has been fetched, that could negatively hamper the efficiency of the application.

EagerLoading: Step 4: To implement the eager loading we have to make two changes in our existing code. first change in employeeContext class and second in our program.cs . Add below statement in employeeContext constructor:

this.Configuration.LazyLoadingEnabled = false;

LazyLoadingEnalbled property set to false disable lazy loading and allow to fetch related entity data  using “Include” when the main entity load in memory. Eagercontext

Step5 : Include related entity with main entity at the time of query execution. Snippet

var query = ContextObj.Employees.Include("EmployeeAddresses").ToList();

eProgram

Step 6: Now again execute above code,see output and track background process with sql profiler. now you can see output is still same as lazy loading but there is a major difference in sql profile analysis report. this time only single query executed to get the parent and child entity details while in lazy loading example different queries initiate to fetch the details. LazyOutput etrace

 

You will see the query at the bottom of the selection that shows the join being applied at the back-end by the SQL Server. This is known as Eager Loading which means loading the related entity data along with the data of the main entity. Now the question arises when to use what option:

Do you need to access many navigation properties from the fetched entities?

No Both options will probably do. However, if the payload your query is bringing is not too big, you may experience performance benefits by using Eager loading as it’ll require less network round trips to materialize your objects. Yes If you need to access many navigation properties from the entities, you’d do that by using multiple include statements in your query with Eager loading. The more entities you include, the bigger the payload your query will return. Once you include three or more entities into your query, consider switching to Lazy loading.

Do you know exactly what data will be needed at run time?

No Lazy loading will be better for you. Otherwise, you may end up querying for data that you will not need. Yes Eager loading is probably your best bet; it will help loading entire sets faster. If your query requires fetching a very large amount of data, and this becomes too slow, then try Lazy loading instead.

Is your code executing far from your database? (increased network latency)

No When the network latency is not an issue, using Lazy loading may simplify your code. Remember that the topology of your application may change, so don’t take database proximity for granted. Yes When the network is a problem, only you can decide what fits better for your scenario. Typically Eager loading will be better because it requires fewer round trips.