Getting started with GraphQL in .NET 6 - Part 2 (Query + Mutation to Database)
Tags: dotnet, graphql, query, mutation
Published: 2021-11-14 17:11:16

Welcome to our second part to learn more about GraphQL! I'm so excited about GraphQL. Since, I just learn this maybe about last 1-3 months. I hope you can give me some advises or some suggestions about my articles. Let's go, we learn more the GraphQL.

## Prepare your tools

1. Since .NET 6 finally released and VS 2022 released too. I use VS 2022 to help me more about Database. But, don't worry, if you use Visual Studio Code, you still can follow step by step, I will bring you some extra steps.

2. Install SQL Server. From [here](https://www.microsoft.com/en-us/sql-server/sql-server-downloads) - if you more familiar with Docker, I suggest you to use the docker, they support in the Linux, check [here](https://hub.docker.com/_/microsoft-mssql-server). That is why I suggest you to use Docker instead, for Linux user. **Note**: If you want to try another databases, feel free to choose your favorite database. You will need to update some code, like dependencies and when settings the DbContext.

## Install Dependencies

Your final code (GraphQLNetExample.csproj) will be like this:

```xml
<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="GraphQL" Version="4.6.1" />
    <PackageReference Include="GraphQL.MicrosoftDI" Version="4.6.1" />
    <PackageReference Include="GraphQL.Server.Authorization.AspNetCore" Version="5.0.2" />
    <PackageReference Include="GraphQL.Server.Transports.AspNetCore.SystemTextJson" Version="5.0.2" />
    <PackageReference Include="GraphQL.Server.Ui.Altair" Version="5.0.2" />
    <PackageReference Include="GraphQL.SystemTextJson" Version="4.6.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.0">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.0">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
  </ItemGroup>

</Project>
```

We are installing some dependencies about EntityFrameworkCore. The manual step is like this (if you use dotnet cli):

1. `dotnet add GraphQLNetExample package Microsoft.EntityFrameworkCore.Design`
2. `dotnet add GraphQLNetExample package Microsoft.EntityFrameworkCore.SqlServer` - feel free to change with your favorite database.
3. `dotnet add GraphQLNetExample package Microsoft.EntityFrameworkCore.Design`

## Prepare our databases

- Create DbContext. My side, write at `EntityFramework/NotesContext.cs`.

```csharp
using GraphQLNetExample.Notes;
using Microsoft.EntityFrameworkCore;

namespace GraphQLNetExample.EntityFramework
{
    public class NotesContext : DbContext
    {
        public DbSet<Note> Notes { get; set; }

        public NotesContext(DbContextOptions options) : base(options)
        {

        }
    }
}
```

- Update `Notes/Note.cs`, in this case, I add `Required` annotation.

```csharp
using System.ComponentModel.DataAnnotations;

namespace GraphQLNetExample.Notes;

public class Note
{
    public Guid Id { get; set; }
    [Required]
    public string Message { get; set; }
}
```

- Update `Program.cs`, we register the DbContext. Again, feel free to setup with your favorite database.

```csharp
// ... another existing code

// Add services to the container.
builder.Services.AddDbContext<NotesContext>(options =>
{
    options.UseSqlServer(builder.Configuration.GetConnectionString("Default"));
});
builder.Services.AddSingleton<ISchema, NotesSchema>(services => new NotesSchema(new SelfActivatingServiceProvider(services)));

// ... another existing code
```

- Update `appsettings.json`, to add the Connection String. Please update the database, User, and Password section with your server configuration.

```json
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "Default": "Server=localhost;Database=graphqltutorial;User Id=sa;Password=;"
  }
}
```

- Don't forget to create your database in SQL Server.

- Add Migration. Because I use Visual Studio 2022, so I can use `Add-Migration BaseNoteModel`, run this command at Package Manager Console. How to navigate? `Tools > NuGet Package Manager > Package Manager Console`.

![Add Migration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lapfepeqbvh9925fnzo6.png)

Note: If you use dotnet ef & dotnet cli, please refer to [this](https://dev.to/berviantoleo/odata-with-net-6-5e1p). In that post, I provide you some steps to use the dotnet cli & dotnet ef with dotnet tools.

- Update database. When use Visual Studio, run this: `Updata-Database`, to make our database sync with the current migration.

![Update Database](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2sme5au17780ygypebeh.png)
 

- Yey, your database is ready!

## Update Query & Add a Mutation

- Create a Mutation file, `Notes/NotesMutation.cs`. We use string type because we only have 1 field only, but if we have larger columns, I suggest to write our input type.

```csharp
using GraphQL;
using GraphQL.Types;
using GraphQLNetExample.EntityFramework;

namespace GraphQLNetExample.Notes
{
    public class NotesMutation : ObjectGraphType
    {
        public NotesMutation()
        {
            Field<NoteType>(
                "createNote",
                arguments: new QueryArguments(
                    new QueryArgument<NonNullGraphType<StringGraphType>> { Name = "message"}
                ),
                resolve: context =>
                {
                    var message = context.GetArgument<string>("message");
                    var notesContext = context.RequestServices.GetRequiredService<NotesContext>();
                    var note = new Note
                    {
                        Message = message,
                    };
                    notesContext.Notes.Add(note);
                    notesContext.SaveChanges();
                    return note;
                }
            );
        }
    }
}
```

- Update our query: `Notes/NotesQuery.cs`. Our final query will looks like this:

```csharp
using GraphQL.Types;
using GraphQLNetExample.EntityFramework;

namespace GraphQLNetExample.Notes;

public class NotesQuery : ObjectGraphType
{
    public NotesQuery()
    {
        Field<ListGraphType<NoteType>>("notes", resolve: context => new List<Note> {
          new Note { Id = Guid.NewGuid(), Message = "Hello World!" },
          new Note { Id = Guid.NewGuid(), Message = "Hello World! How are you?" }
        });
        Field<ListGraphType<NoteType>>("notesFromEF", resolve: context =>
        {
            var notesContext = context.RequestServices.GetRequiredService<NotesContext>();
            return notesContext.Notes.ToList();
        }
        );
    }
}
```

- Register our Mutation to Schema. Update `Notes/NotesSchema.cs`.

```csharp
using GraphQL.Types;

namespace GraphQLNetExample.Notes;

public class NotesSchema : Schema
{
    public NotesSchema(IServiceProvider serviceProvider) : base(serviceProvider)
    {
        Query = serviceProvider.GetRequiredService<NotesQuery>();
        Mutation = serviceProvider.GetRequiredService<NotesMutation>();
    }
}
```

- Yes, your GraphQL is ready!

## Test our GraphQL

- I will test from mutation part first.

```graphql
mutation
{
  createNote(message: "Hello World!")
  {
      id
      message
  }
}
```

![Test Mutation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3t6g9c0wt53vf1f5ytu3.png)
 
- Now, we try to test our query. I add original (in memory), to check the different.

```graphql
{
  notesFromEF {
    id
    message
  }
  notes {
    id
    message
  }
}
```

![Test Query](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h1bxrqodh3xbclmrjwxd.png)
 
## Thank you

For the repository, you can visit here:

{% github bervproject/GraphQLNETExample %}

I suggest you to learn more about data access layer. You can learn from [here](https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-implementation-entity-framework-core). So, hopefully you don't touch DbContext directly. I touch DbContext directly because this is still simple application and small project, if the project more larger, you will need the data access layer.

I'm not sure yet for the third part. Yes, we will have other parts, but not sure yet. Either I will add Authentication/Authorization parts, or just move to how we call the GraphQL in FrontEnd side, I will use the React.js for this. If you have a suggestion, feel free to comment here.

Finally, thank you for your attention and read until this section. Have great days!

![Thank you](https://media.giphy.com/media/W7DHaxkSE4Lpm/giphy.gif)