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

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 call 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.

image.png

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 ICertificaationRepository  
    {  
        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 : ICertificaationRepository  
    {  
        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)  
        {  
        …  
            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.

image.png

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 paste the query which 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 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  
    {  
        …  
       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.

image.png

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

You can download sample from here.