GraphQL In .NET Core Web API With Entity Framework Core - Part Four

Consider a scenario where you have around 200 employees and you want to fetch certificates for each employee and the GetCertifications method expects EmployeeId. That means for each employee, we must use the GetCertifications method. Well, that is not a best practice. So, let’s see how DataLoader will be useful in GraphQL to fetch the data in batches.

In order to enable DataLoader, add the below-highlighted line of code under ConfigureServices in Startup. cs.

DataLoader

Now, modify your existing GetCertificationByEmployee method. Previously we were expected to give EmployeeId, now change it to EmployeeIds, i.e., IEnumerable of long, and fetch the data of certifications from DbContext accordingly.

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace GraphQLInWebApiCore
{
    public interface ICertificationRepository
    {
        Task<ILookup<long, Certification>> GetCertificationByEmployee(IEnumerable<long> employeeIds);
    }
}

using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System;

namespace GraphQLInWebApiCore
{
    public class CertificationRepository : ICertificationRepository
    {
        private readonly GraphQLDemoContext _context;
        public CertificationRepository(GraphQLDemoContext context)
        {
            _context = context;
        }

        public async Task<ILookup<long, Certification>> GetCertificationByEmployee(IEnumerable<long> employeeIds)
        {
            var reviews = await _context.Certification.Where(a => employeeIds.Contains(a.EmployeeId)).ToListAsync();
            return reviews.ToLookup(r => r.EmployeeId);
        }
    }
}

Previously, we added a field of type EmployeeCertificationType as below.

Field<ListGraphType<EmployeeCertificationType>>(
    "certifications",
    resolve: context => certificationRepository.GetCertificationByEmployee(context.Source.Id)
);

Now, we need to create a BatchLoader using DataLoaderContextAccessor and call LoadAsync to load the certification data.

using GraphQL.DataLoader;
using GraphQL.Types;

namespace GraphQLInWebApiCore
{
    public class EmployeeType : ObjectGraphType<Employee>
    {
        public EmployeeType(ICertificaationRepository certificationRepository, IDataLoaderContextAccessor dataLoaderContextAccessor)
        {
            // Other code...

            Field<ListGraphType<EmployeeCertificationType>>(
                "certifications",
                resolve: context =>
                {
                    var loader = dataLoaderContextAccessor.Context.GetOrAddCollectionBatchLoader<long, Certification>(
                        "GetCertificationByEmployee", certificationRepository.GetCertificationByEmployee);

                    return loader.LoadAsync(context.Source.Id);
                });
        }
    }
}

Run the application and execute the same query which we have executed in the previous article. You can see the result, i.e., all employees with their certifications.

Run the application

Let’s expose the same thing from the Web API. Add a GraphQL.Client NuGet package.

In the existing Get method of EmployeeController, just change the query. You can copy and paste the query that we executed in the playground UI.

using GraphQL.Client;
using GraphQL.Common.Request;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace GraphQLGraphTypeFirstNestedTableDataLoader.Controllers
{
    [Route("Employee")]
    public class EmployeeController : Controller
    {
        [HttpGet]
        public async Task<List<Employee>> Get()
        {
            using (GraphQLClient graphQLClient = new GraphQLClient("http://localhost:64666/graphql"))
            {
                var query = new GraphQLRequest
                {
                    Query = @"
                        {
                            employees
                            {
                                name
                                email
                                certifications
                                {
                                    title
                                }
                            }
                        }"
                };
                var response = await graphQLClient.PostAsync(query);
                return response.GetDataFieldAs<List<Employee>>("employees");
            }
        }
    }
}

As we are exposing the Employee model from API, we need to add a list of certifications as one of the properties in Employee.

using System.Collections.Generic;

namespace GraphQLGraphTypeFirstNestedTableDataLoader
{
    public partial class Employee
    {
        // Other code...

        public List<Certification> certifications { get; set; }
    }
}

Run the application, copy the URL from the browser, append with /Employee, and click on the "Send" button.

You can see all the employees with their certifications.

Certifications

So far, we have seen the simple use of GraphQL with single and multiple tables with arguments and how we can expose them through Web API. In the next article, we will see how we can write different kinds of queries in GraphQL.

You can download a sample from here.