Sunday 10 January 2021

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

 In the previous articles of this series, we have configured GraphQL with Employee table. Now, consider a scenario where you want to maintain multiple certifications for each employee. In this situation, we need to create one more table which is a kind of child table for Employee.

You can read the previous parts here.
  • GraphQL In .NET Core Web API With Entity Framework Core - Part One
  • GraphQL In .NET Core Web API With Entity Framework Core - Part Two

Execute the below script to create the Certification table with some dummy data.

  1. CREATE TABLE [dbo].[Certification](  
  2.     [Id] [bigint] IDENTITY(1,1) NOT NULL,  
  3.     [EmployeeId] [bigintNULL,  
  4.     [Title] [varchar](100) NULL,  
  5.     [Month] [intNULL,  
  6.     [Year] [intNULL,  
  7.     [Provider] [varchar](100) NULL,  
  8.  CONSTRAINT [PK_Certification] PRIMARY KEY CLUSTERED   
  9. (  
  10.     [Id] ASC  
  11. )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ONON [PRIMARY]  
  12. ON [PRIMARY]  
  13. GO  
  14. SET IDENTITY_INSERT [dbo].[Certification] ON   
  15. GO  
  16. INSERT [dbo].[Certification] ([Id], [EmployeeId], [Title], [Month], [Year], [Provider]) VALUES (1, 1, N'MCSD', 1, 2019, N'Microsoft')  
  17. GO  
  18. INSERT [dbo].[Certification] ([Id], [EmployeeId], [Title], [Month], [Year], [Provider]) VALUES (2, 1, N'Scrum Master', 2, 2019, N'Agile')  
  19. GO  
  20. INSERT [dbo].[Certification] ([Id], [EmployeeId], [Title], [Month], [Year], [Provider]) VALUES (3, 2, N'MCT', 12, 2018, N'Microsoft')  
  21. GO  
  22. INSERT [dbo].[Certification] ([Id], [EmployeeId], [Title], [Month], [Year], [Provider]) VALUES (4, 2, N'PMP', 1, 2019, N'PMP')  
  23. GO  
  24. SET IDENTITY_INSERT [dbo].[Certification] OFF  
  25. GO  

Execute the Scaffold command in Package Manager Console to update the model and dbContext with Certification table.

Scaffold-DbContext “Server=AKSHAY-PC\DEVSQL2016;Database=GraphQLDemo;Trusted_Connection=True;” Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -force

Post execution, you will be able to see that Certification model is created and DbSet is added for the same in dbContext.

  1. namespace GraphQLInWebApiCore  
  2. {  
  3.     public partial class Certification  
  4.     {  
  5.         public long Id { getset; }  
  6.         public long EmployeeId { getset; }  
  7.         public string Title { getset; }  
  8.         public int? Month { getset; }  
  9.         public int? Year { getset; }  
  10.         public string Provider { getset; }  
  11.     }  
  12. }  
  13.   
  14. public virtual DbSet<Certification> Certification { getset; }  

In the previous example, we created an EmployeeType. Similarly, we need to create a EmployeeCertificationType, which inherits ObjectGraphType.

EmployeeCertificationType.cs

  1. using GraphQL.Types;  
  2.   
  3. namespace GraphQLInWebApiCore  
  4. {  
  5.     public class EmployeeCertificationType : ObjectGraphType<Certification>  
  6.     {  
  7.         public EmployeeCertificationType()  
  8.         {  
  9.             Field(t => t.Id);  
  10.             Field(t => t.Title);  
  11.             Field(t => t.Month, nullable: true);  
  12.             Field(t => t.Year, nullable: true);  
  13.             Field(t => t.Provider);  
  14.         }  
  15.     }  
  16. }  

Create a repository to fetch certificates by employeeId. For that, we need to add ICertificationRepository and CertificationRepository.

  1. using System.Collections.Generic;  
  2. using System.Threading.Tasks;  
  3.   
  4. namespace GraphQLInWebApiCore  
  5. {  
  6.     public interface ICertificaationRepository  
  7.     {  
  8.         Task<List<Certification>> GetCertificationByEmployee(long EmployeeId);  
  9.     }  
  10. }  
  11.   
  12. using Microsoft.EntityFrameworkCore;  
  13. using System.Collections.Generic;  
  14. using System.Linq;  
  15. using System.Threading.Tasks;  
  16.   
  17. namespace GraphQLInWebApiCore  
  18. {  
  19.     public class CertificationRepository : ICertificaationRepository  
  20.     {  
  21.         private readonly GraphQLDemoContext _context;  
  22.         public CertificationRepository(GraphQLDemoContext context)  
  23.         {  
  24.             _context = context;  
  25.         }  
  26.   
  27.         public Task<List<Certification>> GetCertificationByEmployee(long EmployeeId)  
  28.         {  
  29.             return _context.Certification.Where(a => a.Id == EmployeeId).ToListAsync();  
  30.         }  
  31.     }  
  32. }  

Add the below line of code under ConfigureServices in Startup.cs so that it will be added in service collection and later, injected as and when required.

  1. services.AddScoped<ICertificaationRepository, CertificationRepository>();  

As we know, it’s a parent child relationship; i.e., one employee can have multiple certifications. We need to add ListGraphType of EmployeeCertificationType in EmployeeType. So, inject CertificationRepository in EmployeeType constructor.

Add a field of type ListGraphType of EmployeeCertificationType and resolve the context by calling GetCertificationByEmployee method. Here, we need to pass the employeeId as parameter value.

  1. public EmployeeType(ICertificationRepository certificationRepository)  
  2. {  
  3. ….  
  4. }  
  5. using GraphQL.Types;  
  6. namespace GraphQLInWebApiCore  
  7. {  
  8.     public class EmployeeType : ObjectGraphType<Employee>  
  9.     {  
  10.         public EmployeeType(ICertificationRepository certificationRepository)  
  11.         {  
  12.             …     
  13.             Field<ListGraphType<EmployeeCertificationType>>(  
  14.                 "certifications",  
  15.                 resolve: context => certificationRepository.GetCertificationByEmployee(context.Source.Id)  
  16.                 );  
  17.         }  
  18.     }  
  19. }  

Run the application and write the below query.

  1. {  
  2.     employees{  
  3.         name  
  4.         certifications{  
  5.             title  
  6.         }  
  7.     }  
  8. }  

In the above query, you can observe that we have added certifications as one of the fields of employees and we get the result from multiple tables.

GraphQL In .NET Core Web API With Entity Framework Core 

Let’s expose the same thing from the Web API.

Add GraphQL.Client NuGet package.

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

  1. using GraphQL.Client;  
  2. using GraphQL.Common.Request;  
  3. using Microsoft.AspNetCore.Mvc;  
  4. using System.Collections.Generic;  
  5. using System.Threading.Tasks;  
  6.   
  7. namespace GraphQLGraphTypeFirstNestedTable.Controllers  
  8. {  
  9.     [Route("Employee")]  
  10.     public class EmployeeController : Controller  
  11.     {  
  12.         [HttpGet]  
  13.         public async Task<List<Employee>> Get()  
  14.         {  
  15.             using (GraphQLClient graphQLClient = new GraphQLClient("http://localhost:64350/graphql"))  
  16.             {  
  17.                 var query = new GraphQLRequest  
  18.                 {  
  19.                     Query = @"   
  20.                         { employees   
  21.                             { name   
  22.                               email    
  23.                               certifications  
  24.                                  { title }  
  25.                             }  
  26.                         }",  
  27.                 };  
  28.                 var response = await graphQLClient.PostAsync(query);  
  29.                 return response.GetDataFieldAs<List<Employee>>("employees");  
  30.             }  
  31.         }  
  32.     }  
  33. }  

As we are exposing Employee model from API, we need to add List of Certification as one of the properties in Employee

  1. using System.Collections.Generic;  
  2. namespace GraphQLGraphTypeFirstNestedTable  
  3. {  
  4.     public partial class Employee  
  5.     {  
  6.         …  
  7.         public List<Certification> certifications { getset; }  
  8.     }  
  9. }  

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.

GraphQL In .NET Core Web API With Entity Framework Core 

This approach is for understanding purposes only. In real application development, we should use DataLoader to load certifications data. Ideally, it’s not a good practice to load one by one for each request. We will see the DataLoader stuff in the next article.

No comments:

Post a Comment