Skip to content

Commit

Permalink
Small refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim-Maes committed Dec 1, 2023
1 parent 3f5c2e4 commit 8802d34
Show file tree
Hide file tree
Showing 19 changed files with 98 additions and 26 deletions.
2 changes: 1 addition & 1 deletion GraphR.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<package >
<metadata>
<id>GraphR</id>
<version>0.1.6</version>
<version>0.1.7</version>
<authors>Tim Maes</authors>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<license type="expression">MIT</license>
Expand Down
25 changes: 19 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Clean Architecture GraphAPI solution template

Simple Graph API architecture template using Dapper ORM for .NET 8.
## Description

Simple Graph API solution template using Dapper ORM for .NET 8 with clean code, clean architecture and CQRS in mind..
Ideal if you need to set up an Graph API on a existing database. Just install and use the template and start adding queries and mutations.

## Technologies
Expand All @@ -10,6 +12,9 @@ Ideal if you need to set up an Graph API on a existing database. Just install an
- [HotChocolate](https://github.com/ChilliCream/graphql-platform)
- [Bindicate](https://github.com/Tim-Maes/Bindicate)

## Give it a star! :star:
If you have used this template, learned something or like what you see, consider giving it a star!

## Usage

**Install GraphR**
Expand All @@ -29,11 +34,10 @@ The complete solution will be scaffolded inside your folder. Open it in Visual S

![image](https://github.com/Tim-Maes/GraphR/assets/91606949/297e227a-4b55-44e0-ab92-4aa3dc5e7558)


## Setup

Update the `connectionString` in `appsettings.json` and remove the `Seed` folder in the `Infrastructure` project.
Remove the example queries/mutation/repositories and implement your own.
Replace the `connectionString` in `appsettings.json` with your own and remove the `Seed` folder in the `Infrastructure` project.
Remove the example queries/mutation/repositories etc and implement your own.

## Architecture overview

Expand All @@ -43,15 +47,15 @@ A .NET 8 WebAPI application, here we have our GraphAPI endpoint. This applicatio

**Application**

This layer contains all application logic and it depends only on the Domain and Core layer. Here we implement the handlers, mappings and GraphAPI queryies and mutations. This project depends on the Domain and the Core project.
This layer contains all application logic and it depends only on the Domain and Core layer. Here we implement the handlers, graphApi input and output types, queries and mutations. This project depends on the Domain and the Core project.

**Domain**

This will contain all models, enums, exceptions, interfaces, types and logic specific to the domain layer. This project references no other project.

**Infrastructure**

In this layer we implement the data access (repositories, Dapper implementation,..) and possibly classes to access other external resources. These classes should be based on interfaces defined within the application layer.
In this layer we implement the data access (repositories, Dapper implementation, EntityMaps..) and possibly classes to access other external resources. These classes should be based on interfaces defined within the application layer.

**Core**

Expand All @@ -60,3 +64,12 @@ This project holds some core logic that we need in our solution. In the template
## Autowiring

This project uses the `Bindicate` library to autowire dependencies by using attributes, so we don't bloat the `ServiceCollectionExtensions`.


## Test the API

Build and run the project, and navigate to <localhost>/graphql, this will take you to the Banana Cake Pop playground where you can find the graphql schema:


You can play around in the Banana Cake Pop playground and test out a query.
For example:
2 changes: 2 additions & 0 deletions src/GraphR.Application/Authors/AuthorsQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ public sealed class AuthorsQuery
{
public async Task<AuthorDto> Author([Service] IGetAuthorByIdHandler handler, AuthorParameters parameters)
=> await handler.Handle(parameters);

public async Task<AuthorDto[]> Authors([Service] IGetAuthorsQueryHandler handler) => await handler.Handle();
}
21 changes: 21 additions & 0 deletions src/GraphR.Application/Authors/Handlers/GetAuthorsQueryHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using GraphR.Application.Authors.Types.Mappings;
using GraphR.Application.Authors.Types.Output;
using GraphR.Domain.Interfaces;
using GrapR.Core.Handlers;

namespace GraphR.Application.Authors.Handlers;

internal sealed class GetAuthorsQueryHandler : Handler<AuthorDto[]>, IGetAuthorsQueryHandler
{
private readonly IAuthorRepository _repository;

public GetAuthorsQueryHandler(IAuthorRepository repository)
{
_repository = repository;
}

public override async Task<AuthorDto[]> Handle()
=> (await _repository.GetAll()).ToOutput();
}

public interface IGetAuthorsQueryHandler : IHandler<AuthorDto[]> { }
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
namespace GraphR.Application.Authors.Types.Input;

public sealed class AuthorParameters
{
public int Id { get; set; }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
using GraphR.Application.Authors.Types.Output;
using GrapR.Domain.Models;
using GraphR.Domain.Entities;

namespace GraphR.Application.Authors.Types.Mappings;

internal static class AuthorMapping
{
internal static AuthorDto[] ToOutput(this Author[] authors)
=> authors.Select(ToOutput).ToArray();

internal static AuthorDto ToOutput(this Author author)
=> new AuthorDto
{
Id = author.Id,
Name = author.Name,
Biography = author.Biography,
};
}
2 changes: 2 additions & 0 deletions src/GraphR.Application/Authors/Types/Output/AuthorDto.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ public sealed class AuthorDto
public int Id { get; set; }

public string Name { get; set; }

public string Biography { get; set; }
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using FluentValidation;
using GraphR.Application.Books.Types.Input;
using GraphR.Domain.Enums;
using GrapR.Core.Handlers;
using GrapR.Domain.Enums;
using GrapR.Domain.Interfaces;

namespace GraphR.Application.Books.Handlers.Mutation;
Expand Down
2 changes: 1 addition & 1 deletion src/GraphR.Application/Books/Types/Mappings/BookMapping.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using GraphR.Application.Books.Types.Output;
using GrapR.Domain.Models;
using GraphR.Domain.Entities;

namespace GraphR.Application.Books.Types.Mappings;

Expand Down
5 changes: 1 addition & 4 deletions src/GraphR.Application/GraphR.Application.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
Expand All @@ -11,9 +11,6 @@
<ProjectReference Include="..\GraphR.Domain\GraphR.Domain.csproj" />

</ItemGroup>
<ItemGroup>
<Folder Include="Authors\Handlers\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="HotChocolate.Abstractions" Version="13.7.0" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace GrapR.Domain.Models;
namespace GraphR.Domain.Entities;

public sealed class Author
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using GrapR.Domain.Enums;
using GraphR.Domain.Enums;

namespace GrapR.Domain.Models;
namespace GraphR.Domain.Entities;

public sealed class Book
{
Expand Down
2 changes: 1 addition & 1 deletion src/GraphR.Domain/Enums/Category.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace GrapR.Domain.Enums;
namespace GraphR.Domain.Enums;

public enum Category
{
Expand Down
4 changes: 3 additions & 1 deletion src/GraphR.Domain/Interfaces/IAuthorRepository.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using GrapR.Domain.Models;
using GraphR.Domain.Entities;

namespace GraphR.Domain.Interfaces;
public interface IAuthorRepository
{
Task<Author> GetById(int id);

Task<Author[]> GetAll();
}
4 changes: 2 additions & 2 deletions src/GraphR.Domain/Interfaces/IBookRepository.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using GrapR.Domain.Enums;
using GrapR.Domain.Models;
using GraphR.Domain.Entities;
using GraphR.Domain.Enums;

namespace GrapR.Domain.Interfaces;

Expand Down
14 changes: 14 additions & 0 deletions src/GraphR.Infrastructure/Maps/AuthorMap.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Dapper.FluentMap.Mapping;
using GraphR.Domain.Entities;

namespace GraphR.Infrastructure.Maps;

internal class AuthorMap : EntityMap<Author>
{
public AuthorMap()
{
Map(x => x.Id).ToColumn("Id");
Map(x => x.Name).ToColumn("Name");
Map(x => x.Biography).ToColumn("Biography");
}
}
4 changes: 2 additions & 2 deletions src/GraphR.Infrastructure/Maps/BookMap.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using GrapR.Domain.Models;
using GraphR.Domain.Entities;
using Dapper.FluentMap.Mapping;

namespace GraphR.Application.Books.Maps;
namespace GraphR.Infrastructure.Maps;

internal class BookMap : EntityMap<Book>
{
Expand Down
18 changes: 17 additions & 1 deletion src/GraphR.Infrastructure/Repositories/AuthorRepository.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using Bindicate.Attributes;
using Dapper;
using GraphR.Domain.Entities;
using GraphR.Domain.Exceptions;
using GraphR.Domain.Interfaces;
using GrapR.Domain.Models;
using GrapR.Infrastructure.Database;

namespace GrapR.Infrastructure.Repositories;
Expand All @@ -17,6 +17,22 @@ public AuthorRepository(IDbConnectionProvider dbConnectionProvider)
_dbConnectionProvider = dbConnectionProvider;
}

public async Task<Author[]> GetAll()
{

var query =
"""
SELECT Name, Biography
FROM dbo.Author
""";

using (var connection = _dbConnectionProvider.CreateConnection())
{
return (await connection.QueryAsync<Author>(
sql: query)).ToArray();
}
}

public async Task<Author> GetById(int id)
{
var query =
Expand Down
4 changes: 2 additions & 2 deletions src/GraphR.Infrastructure/Repositories/BookRepository.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
using Bindicate.Attributes;
using GrapR.Domain.Exceptions;
using GrapR.Domain.Interfaces;
using GrapR.Domain.Models;
using GraphR.Domain.Entities;
using GrapR.Infrastructure.Database;
using Dapper;
using GrapR.Domain.Enums;
using GraphR.Domain.Enums;

namespace GrapR.Infrastructure.Repositories;

Expand Down

0 comments on commit 8802d34

Please sign in to comment.