Introduction
We will try to do a CRUD operation using graphQL with Hot Chocolate using Asp.net Core.
First of all we will understand what GraphQL and Hot Chocolate are.
GraphQL
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.
GraphQL follows the same set of constraints as REST APIs, but it organizes data into a graph using one interface. Objects are represented by nodes (defined using the GraphQL schema), and the relationship between nodes is represented by edges in the graph. Each object is then backed by a resolver that accesses the server’s data.
Hot Chocolate
Hot Chocolate is a .NET GraphQL platform that can help you build a GraphQL layer over your existing and new infrastructure.
Our API will let you start very quickly with pre-built templates that let you start in seconds.
Pre Requirements
- Sql server 2019
- Visual studio
Now we start.
Firstly come to SQL server and create tables.
- SET ANSI_NULLS ON
- GO
- SET QUOTED_IDENTIFIER ON
- GO
- CREATE TABLE [dbo].[Department](
- [DepartmentId] [int] IDENTITY(1,1) NOT NULL,
- [Name] [varchar](50) NULL,
- CONSTRAINT [PK_Department] PRIMARY KEY CLUSTERED
- (
- [DepartmentId] ASC
- )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
- ) ON [PRIMARY]
- GO
- SET ANSI_NULLS ON
- GO
- SET QUOTED_IDENTIFIER ON
- GO
- CREATE TABLE [dbo].[Employee](
- [EmployeeId] [int] IDENTITY(1,1) NOT NULL,
- [Name] [varchar](50) NULL,
- [Email] [varchar](50) NULL,
- [Age] [int] NULL,
- [DepartmentId] [int] NULL,
- CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED
- (
- [EmployeeId] ASC
- )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
- ) ON [PRIMARY]
- GO
Now come to Visual Studio and create a new web application.
After that you add some nuget package
Below are the list of nuget packages:
- Install-Package Microsoft.EntityFrameworkCore -Version 5.0.3
- Install-Package Microsoft.EntityFrameworkCore.SqlServer
- Install-Package HotChocolate -Version 11.0.9
- Install-Package HotChocolate.AspNetCore -Version 11.0.9
- Install-Package GraphQL
- Install-Package graphiql -Version 2.0.0
Now in your project you haveto add folder model.
Under the model create a class department.
- using System;
- using System.Collections.Generic;
- using System.ComponentModel.DataAnnotations;
- using System.ComponentModel.DataAnnotations.Schema;
- using System.Linq;
- using System.Threading.Tasks;
- namespace Asp.netCoreGraphQL.Model {
- public class Department {
- [Key]
- [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
- public int DepartmentId {
- get;
- set;
- }
- public string Name {
- get;
- set;
- }
- public ICollection < Employee > Employees {
- get;
- set;
- }
- }
- }
In the above class you see <Employee> error not found ,
So now we create a new class under the model folder employee.
- using System;
- using System.Collections.Generic;
- using System.ComponentModel.DataAnnotations;
- using System.ComponentModel.DataAnnotations.Schema;
- using System.Linq;
- using System.Threading.Tasks;
- namespace Asp.netCoreGraphQL.Model {
- public class Employee {
- [Key]
- [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
- public int EmployeeId {
- get;
- set;
- }
- [Required]
- public string Name {
- get;
- set;
- }
- [Required]
- [EmailAddress]
- public string Email {
- get;
- set;
- }
- [Required]
- [Range(minimum: 20, maximum: 50)]
- public int Age {
- get;
- set;
- }
- public int DepartmentId {
- get;
- set;
- }
- public Department Department {
- get;
- set;
- }
- }
- }
Now create a DbContext class under the Model Folder SampleAppDbContext
- using Microsoft.EntityFrameworkCore;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
- namespace Asp.netCoreGraphQL.Model {
- public class SampleAppDbContext: DbContext {
- public SampleAppDbContext(DbContextOptions < SampleAppDbContext > options): base(options) {}
- public DbSet < Employee > Employee {
- get;
- set;
- }
- public DbSet < Department > Department {
- get;
- set;
- }
- }
- }
Now add connectionstrings in the appsettings.json file.
- {
- "ConnectionStrings": {
- "SampleAppDbContext": "Data Source=AJAYKUMAR-VWIPL\\MSSQLSERVERS;Initial Catalog=Test;Integrated Security=True;"
- },
- "Logging": {
- "LogLevel": {
- "Default": "Information",
- "Microsoft": "Warning",
- "Microsoft.Hosting.Lifetime": "Information"
- }
- },
- "AllowedHosts": "*"
- }
Now create a new folder repository.
Under the repository folder we have a class DepartmentRepository
- using Asp.netCoreGraphQL.Model;
- using Microsoft.EntityFrameworkCore;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
- namespace Asp.netCoreGraphQL.Repository {
- public class DepartmentRepository {
- private readonly SampleAppDbContext _sampleAppDbContext;
- public DepartmentRepository(SampleAppDbContext sampleAppDbContext) {
- _sampleAppDbContext = sampleAppDbContext;
- }
- public List < Department > GetAllDepartmentOnly() {
- return _sampleAppDbContext.Department.ToList();
- }
- public List < Department > GetAllDepartmentsWithEmployee() {
- return _sampleAppDbContext.Department.Include(d => d.Employees).ToList();
- }
- public async Task < Department > CreateDepartment(Department department) {
- await _sampleAppDbContext.Department.AddAsync(department);
- await _sampleAppDbContext.SaveChangesAsync();
- return department;
- }
- }
- }
And now under repository folder create another class EmployeeRepository.
- using Asp.netCoreGraphQL.Model;
- using Microsoft.EntityFrameworkCore;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
- namespace Asp.netCoreGraphQL.Repository {
- public class EmployeeRepository {
- private readonly SampleAppDbContext _sampleAppDbContext;
- public EmployeeRepository(SampleAppDbContext sampleAppDbContext) {
- _sampleAppDbContext = sampleAppDbContext;
- }
- public List < Employee > GetEmployees() {
- return _sampleAppDbContext.Employee.ToList();
- }
- public Employee GetEmployeeById(int id) {
- var employee = _sampleAppDbContext.Employee.Include(e => e.Department).Where(e => e.EmployeeId == id).FirstOrDefault();
- if (employee != null) return employee;
- return null;
- }
- public async Task < Employee > UPdateEmployeeByIdAsync(int id, string Name) {
- var employee = _sampleAppDbContext.Employee.Include(e => e.Department).Where(e => e.EmployeeId == id).FirstOrDefault();
- employee.Name = Name;
- await _sampleAppDbContext.SaveChangesAsync();
- if (employee != null) return employee;
- return null;
- }
- public List < Employee > GetEmployeesWithDepartment() {
- return _sampleAppDbContext.Employee.Include(e => e.Department).ToList();
- }
- public async Task < Employee > CreateEmployee(Employee employee) {
- await _sampleAppDbContext.Employee.AddAsync(employee);
- await _sampleAppDbContext.SaveChangesAsync();
- return employee;
- }
- }
- }
Now we have create new folder DataAccess.
Under the DataAcess folder to create a class Mutation.
- using Asp.netCoreGraphQL.Model;
- using Asp.netCoreGraphQL.Repository;
- using HotChocolate;
- using HotChocolate.Subscriptions;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
- namespace Asp.netCoreGraphQL.DataAccess {
- public class Mutation {
- public async Task < Department > CreateDepartment([Service] DepartmentRepository departmentRepository,
- [Service] ITopicEventSender eventSender, string departmentName) {
- var newDepartment = new Department {
- Name = departmentName
- };
- var createdDepartment = await departmentRepository.CreateDepartment(newDepartment);
- await eventSender.SendAsync("DepartmentCreated", createdDepartment);
- return createdDepartment;
- }
- public async Task < Employee > CreateEmployeeWithDepartmentId([Service] EmployeeRepository employeeRepository, string name, int age, string email, int departmentId) {
- Employee newEmployee = new Employee {
- Name = name,
- Age = age,
- Email = email,
- DepartmentId = departmentId
- };
- var createdEmployee = await employeeRepository.CreateEmployee(newEmployee);
- return createdEmployee;
- }
- public async Task < Employee > CreateEmployeeWithDepartment([Service] EmployeeRepository employeeRepository, string name, int age, string email, string departmentName) {
- Employee newEmployee = new Employee {
- Name = name,
- Age = age,
- Email = email,
- Department = new Department {
- Name = departmentName
- }
- };
- var createdEmployee = await employeeRepository.CreateEmployee(newEmployee);
- return createdEmployee;
- }
- }
- }
Now create anothe class under the DataAccess folder query.
- using Asp.netCoreGraphQL.Model;
- using Asp.netCoreGraphQL.Repository;
- using HotChocolate;
- using HotChocolate.Subscriptions;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
- namespace Asp.netCoreGraphQL.DataAccess {
- public class Query {
- public List < Employee > AllEmployeeOnly([Service] EmployeeRepository employeeRepository) => employeeRepository.GetEmployees();
- public List < Employee > AllEmployeeWithDepartment([Service] EmployeeRepository employeeRepository) => employeeRepository.GetEmployeesWithDepartment();
- public async Task < Employee > GetEmployeeById([Service] EmployeeRepository employeeRepository,
- [Service] ITopicEventSender eventSender, int id) {
- Employee gottenEmployee = employeeRepository.GetEmployeeById(id);
- await eventSender.SendAsync("ReturnedEmployee", gottenEmployee);
- return gottenEmployee;
- }
- public async Task < Employee > UpdateEmployeeById([Service] EmployeeRepository employeeRepository,
- [Service] ITopicEventSender eventSender, int id, string name) {
- Employee gottenEmployee = await employeeRepository.UPdateEmployeeByIdAsync(id, name);
- await eventSender.SendAsync("ReturnedEmployee", gottenEmployee);
- return gottenEmployee;
- }
- public List < Department > AllDepartmentsOnly([Service] DepartmentRepository departmentRepository) => departmentRepository.GetAllDepartmentOnly();
- public List < Department > AllDepartmentsWithEmployee([Service] DepartmentRepository departmentRepository) => departmentRepository.GetAllDepartmentsWithEmployee();
- }
- }
Now create another class under the DataAccess folder subscription
- using Asp.netCoreGraphQL.Model;
- using HotChocolate;
- using HotChocolate.Execution;
- using HotChocolate.Subscriptions;
- using HotChocolate.Types;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading;
- using System.Threading.Tasks;
- namespace Asp.netCoreGraphQL.DataAccess {
- public class Subscription {
- [SubscribeAndResolve]
- public async ValueTask < ISourceStream < Department >> OnDepartmentCreate([Service] ITopicEventReceiver eventReceiver, CancellationToken cancellationToken) {
- return await eventReceiver.SubscribeAsync < string, Department > ("DepartmentCreated", cancellationToken);
- }
- [SubscribeAndResolve]
- public async ValueTask < ISourceStream < Employee >> OnEmployeeGet([Service] ITopicEventReceiver eventReceiver, CancellationToken cancellationToken) {
- return await eventReceiver.SubscribeAsync < string, Employee > ("ReturnedEmployee", cancellationToken);
- }
- }
- }
Now change under the Startup.cs
- using Asp.netCoreGraphQL.DataAccess;
- using Asp.netCoreGraphQL.Model;
- using Asp.netCoreGraphQL.Repository;
- using Microsoft.AspNetCore.Builder;
- using Microsoft.AspNetCore.Hosting;
- using Microsoft.EntityFrameworkCore;
- using Microsoft.Extensions.Configuration;
- using Microsoft.Extensions.DependencyInjection;
- using Microsoft.Extensions.Hosting;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
- namespace Asp.netCoreGraphQL {
- public class Startup {
- private readonly string AllowedOrigin = "allowedOrigin";
- public Startup(IConfiguration configuration) {
- Configuration = configuration;
- }
- public IConfiguration Configuration {
- get;
- }
-
- public void ConfigureServices(IServiceCollection services) {
-
- services.AddDbContext < SampleAppDbContext > (options => options.UseSqlServer(Configuration.GetConnectionString("SampleAppDbContext")));
- services.AddInMemorySubscriptions();
- services.AddGraphQLServer().AddQueryType < Query > ().AddMutationType < Mutation > ().AddSubscriptionType < Subscription > ();
- services.AddScoped < EmployeeRepository, EmployeeRepository > ();
- services.AddScoped < DepartmentRepository, DepartmentRepository > ();
- services.AddCors(option => {
- option.AddPolicy("allowedOrigin", builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
- });
- }
-
- public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
- if (env.IsDevelopment()) {
- app.UseDeveloperExceptionPage();
- }
- app.UseCors(AllowedOrigin);
- app.UseWebSockets();
- app.UseRouting().UseEndpoints(endpoints => {
- endpoints.MapGraphQL();
- });
- }
- }
- }
Now the coding part is done and we can execute the code.
After The url you add /graphql/
Your URL looks like:
http://localhost:61280/graphql/
This is called Banana Cake popup.
Now we start our CRUD operation.
Create Query
- mutation {
- createEmployeeWithDepartment(name: "Ajay", age: 30, email: "[email protected]", departmentName: "IT") {
- departmentId
- name
- department {
- departmentId
- name
- }
- }
- }
In BananaCake popup you see execute button. In the left hand side there are inputs and in the right hand side there are responses.
Show The OutPut
- query {
- allDepartmentsWithEmployee {
- name
- employees {
- email
- name
- }
- }
- }
The response:
- {
- "data": {
- "allDepartmentsWithEmployee": [{
- "name": "IT",
- "employees": [{
- "email": "[email protected]",
- "name": "Ajay"
- }]
- }]
- }
- }
Show the output using some filter
- query {
- employeeById(id: 16) {
- name
- email
- }
- }
Response:
Update the code:
- query {
- updateEmployeeById(id: 16, name: "Ajay Kumar") {
- name,
- email,
- department {
- name
- }
- }
- }
Response
- {
- "data": {
- "updateEmployeeById": {
- "name": "Ajay Kumar",
- "email": "[email protected]",
- "department": {
- "name": "IT"
- }
- }
- }
- }
NOTE
You can run your graphQL query using the postman
I have done CRUD operation using GraphQL with Hot Chocolate using asp.net core. I hope you understand. If you have any query and suggestion then please leave a comment.