-
-
Notifications
You must be signed in to change notification settings - Fork 63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add EF Core based DataLoader sample with queries and mutation #110
Merged
tlil
merged 15 commits into
graphql-dotnet:master
from
huysentruitw:sample/dataloader-efcore
Oct 23, 2018
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
4f03740
Initial commit (project scaffold)
huysentruitw 4a298d0
Add Data stuff
huysentruitw 5abca07
Add GraphQL boilerplate
huysentruitw 3f9a7e2
Add migrations
huysentruitw 41106bc
wip
huysentruitw f28c941
Add queries
huysentruitw b6d1fcc
Inject IUserContext instead of UserContext in GraphController
huysentruitw 3e0a157
Inject IUserContext instead of UserContext in GraphController
huysentruitw 8625869
Move sample to subfolder
huysentruitw 495e564
Update README.md
huysentruitw d687159
Fix async/await calls
huysentruitw 99c5cc5
Add UpdateMovieTitle mutation
huysentruitw 47ec6dc
Update README.md
huysentruitw 5fbfa6c
Remove unused DataLoaderSynchronizationContext
huysentruitw e90f8ca
Fix indentation in README.md
huysentruitw File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
| ||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
# Visual Studio 15 | ||
VisualStudioVersion = 15.0.28010.2046 | ||
MinimumVisualStudioVersion = 10.0.40219.1 | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataLoaderWithEFCore", "DataLoaderWithEFCore\DataLoaderWithEFCore.csproj", "{0FF0D230-70D4-49DC-8545-0B120F534EFC}" | ||
EndProject | ||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B32B920C-751D-4C3F-B326-329A17E19B56}" | ||
ProjectSection(SolutionItems) = preProject | ||
README.md = README.md | ||
EndProjectSection | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|Any CPU = Debug|Any CPU | ||
Release|Any CPU = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{0FF0D230-70D4-49DC-8545-0B120F534EFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{0FF0D230-70D4-49DC-8545-0B120F534EFC}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{0FF0D230-70D4-49DC-8545-0B120F534EFC}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{0FF0D230-70D4-49DC-8545-0B120F534EFC}.Release|Any CPU.Build.0 = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(SolutionProperties) = preSolution | ||
HideSolutionNode = FALSE | ||
EndGlobalSection | ||
GlobalSection(ExtensibilityGlobals) = postSolution | ||
SolutionGuid = {11561377-1EAE-4B0F-B09C-D5F3C051F341} | ||
EndGlobalSection | ||
EndGlobal |
20 changes: 20 additions & 0 deletions
20
samples/DataLoaderWithEFCore/DataLoaderWithEFCore/Data/Models/Actor.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
using System; | ||
using System.ComponentModel.DataAnnotations; | ||
|
||
namespace DataLoaderWithEFCore.Data.Models | ||
{ | ||
public class Actor | ||
{ | ||
[Key] | ||
public Guid Id { get; set; } | ||
|
||
[MaxLength(200), Required] | ||
public string Name { get; set; } | ||
|
||
[MaxLength(2), Required] | ||
public string CountryCode { get; set; } | ||
|
||
[Required] | ||
public Guid MovieId { get; set; } | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
samples/DataLoaderWithEFCore/DataLoaderWithEFCore/Data/Models/Country.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
using System.ComponentModel.DataAnnotations; | ||
|
||
namespace DataLoaderWithEFCore.Data.Models | ||
{ | ||
public class Country | ||
{ | ||
[Key, MaxLength(2)] | ||
public string Code { get; set; } | ||
|
||
public string Name { get; set; } | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
samples/DataLoaderWithEFCore/DataLoaderWithEFCore/Data/Models/Movie.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
using System; | ||
using System.ComponentModel.DataAnnotations; | ||
|
||
namespace DataLoaderWithEFCore.Data.Models | ||
{ | ||
public class Movie | ||
{ | ||
[Key] | ||
public Guid Id { get; set; } | ||
|
||
[MaxLength(500), Required] | ||
public string Title { get; set; } | ||
|
||
[MaxLength(50), Required] | ||
public string Genre { get; set; } | ||
|
||
[Required] | ||
public DateTime ReleaseDateUtc { get; set; } | ||
} | ||
} |
50 changes: 50 additions & 0 deletions
50
samples/DataLoaderWithEFCore/DataLoaderWithEFCore/Data/MovieDbContext.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
using System; | ||
using DataLoaderWithEFCore.Data.Models; | ||
using Microsoft.EntityFrameworkCore; | ||
|
||
namespace DataLoaderWithEFCore.Data | ||
{ | ||
public class MovieDbContext : DbContext | ||
{ | ||
public MovieDbContext(DbContextOptions<MovieDbContext> options) | ||
: base(options) | ||
{ | ||
} | ||
|
||
public virtual DbSet<Actor> Actors { get; set; } | ||
|
||
public virtual DbSet<Country> Countries { get; set; } | ||
|
||
public virtual DbSet<Movie> Movies { get; set; } | ||
|
||
protected override void OnModelCreating(ModelBuilder modelBuilder) | ||
{ | ||
base.OnModelCreating(modelBuilder); | ||
|
||
var movie1 = new Movie { Id = Guid.NewGuid(), Title = "Johnny English Strikes Again", Genre = "Action/Adventure", ReleaseDateUtc = DateTime.Parse("10/12/2018 00:00:00Z") }; | ||
var movie2 = new Movie { Id = Guid.NewGuid(), Title = "A Star Is Born", Genre = "Drama/Romance", ReleaseDateUtc = DateTime.Parse("10/04/2018 00:00:00Z") }; | ||
|
||
modelBuilder.Entity<Actor>().HasData( | ||
new Actor { Id = Guid.NewGuid(), CountryCode = "UK", Name = "Rowan Atkinson", MovieId = movie1.Id }, | ||
new Actor { Id = Guid.NewGuid(), CountryCode = "FR", Name = "Olga Kurylenko", MovieId = movie1.Id }, | ||
new Actor { Id = Guid.NewGuid(), CountryCode = "US", Name = "Jake Lacy", MovieId = movie1.Id }, | ||
new Actor { Id = Guid.NewGuid(), CountryCode = "US", Name = "Bradley Cooper", MovieId = movie2.Id }, | ||
new Actor { Id = Guid.NewGuid(), CountryCode = "US", Name = "Lady Gaga", MovieId = movie2.Id }, | ||
new Actor { Id = Guid.NewGuid(), CountryCode = "US", Name = "Sam Elliott", MovieId = movie2.Id }, | ||
new Actor { Id = Guid.NewGuid(), CountryCode = "US", Name = "Andrew Dice Clay", MovieId = movie2.Id }, | ||
new Actor { Id = Guid.NewGuid(), CountryCode = "US", Name = "Dave Chappelle", MovieId = movie2.Id }, | ||
new Actor { Id = Guid.NewGuid(), CountryCode = "US", Name = "Rebecca Field", MovieId = movie2.Id }, | ||
new Actor { Id = Guid.NewGuid(), CountryCode = "US", Name = "Michael Harney", MovieId = movie2.Id }, | ||
new Actor { Id = Guid.NewGuid(), CountryCode = "US", Name = "Rafi Gavron", MovieId = movie2.Id }, | ||
new Actor { Id = Guid.NewGuid(), CountryCode = "US", Name = "Willam Belli", MovieId = movie2.Id }, | ||
new Actor { Id = Guid.NewGuid(), CountryCode = "US", Name = "Halsey", MovieId = movie2.Id }); | ||
|
||
modelBuilder.Entity<Country>().HasData( | ||
new Country { Code = "UK", Name = "United Kingdom" }, | ||
new Country { Code = "FR", Name = "France" }, | ||
new Country { Code = "US", Name = "United States" }); | ||
|
||
modelBuilder.Entity<Movie>().HasData(movie1, movie2); | ||
} | ||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
samples/DataLoaderWithEFCore/DataLoaderWithEFCore/Data/Repositories/ActorRepository.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using DataLoaderWithEFCore.Data.Models; | ||
using Microsoft.EntityFrameworkCore; | ||
|
||
namespace DataLoaderWithEFCore.Data.Repositories | ||
{ | ||
public interface IActorRepository | ||
{ | ||
Task<ILookup<Guid, Actor>> GetActorsPerMovie(IEnumerable<Guid> movieIds); | ||
} | ||
|
||
public class ActorRepository : IActorRepository | ||
{ | ||
private readonly MovieDbContext _context; | ||
|
||
public ActorRepository(MovieDbContext context) | ||
{ | ||
_context = context; | ||
} | ||
|
||
public async Task<ILookup<Guid, Actor>> GetActorsPerMovie(IEnumerable<Guid> movieIds) | ||
=> (await _context.Actors | ||
.AsNoTracking() | ||
.Where(x => movieIds.Contains(x.MovieId)) | ||
.ToArrayAsync()) | ||
.ToLookup(x => x.MovieId); | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
samples/DataLoaderWithEFCore/DataLoaderWithEFCore/Data/Repositories/CountryRepository.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using DataLoaderWithEFCore.Data.Models; | ||
using Microsoft.EntityFrameworkCore; | ||
|
||
namespace DataLoaderWithEFCore.Data.Repositories | ||
{ | ||
public interface ICountryRepository | ||
{ | ||
Task<IDictionary<string, Country>> GetCountries(IEnumerable<string> countryCodes); | ||
} | ||
|
||
public class CountryRepository : ICountryRepository | ||
{ | ||
private readonly MovieDbContext _context; | ||
|
||
public CountryRepository(MovieDbContext context) | ||
{ | ||
_context = context; | ||
} | ||
|
||
public async Task<IDictionary<string, Country>> GetCountries(IEnumerable<string> countryCodes) | ||
=> await _context.Countries | ||
.AsNoTracking() | ||
.Where(x => countryCodes.Contains(x.Code)) | ||
.ToDictionaryAsync(x => x.Code); | ||
} | ||
} |
44 changes: 44 additions & 0 deletions
44
samples/DataLoaderWithEFCore/DataLoaderWithEFCore/Data/Repositories/MovieRepository.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
using System; | ||
using System.Threading.Tasks; | ||
using DataLoaderWithEFCore.Data.Models; | ||
using Microsoft.EntityFrameworkCore; | ||
|
||
namespace DataLoaderWithEFCore.Data.Repositories | ||
{ | ||
public interface IMovieRepository | ||
{ | ||
Task<Movie> FindMovie(Guid id); | ||
|
||
Task<Movie[]> GetMovies(); | ||
|
||
Task<Movie> UpdateMovieTitle(Guid id, string newTitle); | ||
} | ||
|
||
public class MovieRepository : IMovieRepository | ||
{ | ||
private readonly MovieDbContext _context; | ||
|
||
public MovieRepository(MovieDbContext context) | ||
{ | ||
_context = context; | ||
} | ||
|
||
public async Task<Movie> FindMovie(Guid id) | ||
=> await _context.Movies.AsNoTracking().FirstOrDefaultAsync(x => x.Id == id); | ||
|
||
public async Task<Movie[]> GetMovies() | ||
=> await _context.Movies.AsNoTracking().ToArrayAsync(); | ||
|
||
public async Task<Movie> UpdateMovieTitle(Guid id, string newTitle) | ||
{ | ||
var movie = await FindMovie(id); | ||
if (movie == null) | ||
throw new InvalidOperationException($"Movie with id {id} not found"); | ||
|
||
movie.Title = newTitle; | ||
_context.Movies.Update(movie); | ||
await _context.SaveChangesAsync(); | ||
return movie; | ||
} | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
samples/DataLoaderWithEFCore/DataLoaderWithEFCore/DataLoaderWithEFCore.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<Project Sdk="Microsoft.NET.Sdk.Web"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>netcoreapp2.1</TargetFramework> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<Compile Remove="wwwroot\**" /> | ||
<Content Remove="wwwroot\**" /> | ||
<EmbeddedResource Remove="wwwroot\**" /> | ||
<None Remove="wwwroot\**" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="AutoMapper" Version="7.0.1" /> | ||
<PackageReference Include="GraphQL.Conventions" Version="2.0.1" /> | ||
<PackageReference Include="Microsoft.AspNetCore.App" /> | ||
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.1.2" PrivateAssets="All" /> | ||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.1.4" /> | ||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.5" /> | ||
</ItemGroup> | ||
|
||
</Project> |
61 changes: 61 additions & 0 deletions
61
samples/DataLoaderWithEFCore/DataLoaderWithEFCore/GraphApi/GraphController.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
using System.IO; | ||
using System.Linq; | ||
using System.Net; | ||
using System.Threading.Tasks; | ||
using GraphQL; | ||
using GraphQL.Conventions; | ||
using Microsoft.AspNetCore.Mvc; | ||
|
||
namespace DataLoaderWithEFCore.GraphApi | ||
{ | ||
[ApiController] | ||
[Route("api/graph")] | ||
public class GraphController : ControllerBase | ||
{ | ||
private readonly GraphQLEngine _engine; | ||
private readonly IUserContext _userContext; | ||
private readonly IDependencyInjector _injector; | ||
|
||
public GraphController(GraphQLEngine engine, IUserContext userContext, IDependencyInjector injector) | ||
{ | ||
_engine = engine; | ||
_userContext = userContext; | ||
_injector = injector; | ||
} | ||
|
||
[HttpPost] | ||
public async Task<IActionResult> Post() | ||
{ | ||
string requestBody; | ||
using (var reader = new StreamReader(Request.Body)) | ||
requestBody = await reader.ReadToEndAsync(); | ||
|
||
ExecutionResult result = await _engine | ||
.NewExecutor() | ||
.WithUserContext(_userContext) | ||
.WithDependencyInjector(_injector) | ||
.WithRequest(requestBody) | ||
.Execute(); | ||
|
||
var responseBody = _engine.SerializeResult(result); | ||
|
||
HttpStatusCode statusCode = HttpStatusCode.OK; | ||
|
||
if (result.Errors?.Any() ?? false) | ||
{ | ||
statusCode = HttpStatusCode.InternalServerError; | ||
if (result.Errors.Any(x => x.Code == "VALIDATION_ERROR")) | ||
statusCode = HttpStatusCode.BadRequest; | ||
else if (result.Errors.Any(x => x.Code == "UNAUTHORIZED_ACCESS")) | ||
statusCode = HttpStatusCode.Forbidden; | ||
} | ||
|
||
return new ContentResult | ||
{ | ||
Content = responseBody, | ||
ContentType = "application/json; charset=utf-8", | ||
StatusCode = (int)statusCode | ||
}; | ||
} | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
samples/DataLoaderWithEFCore/DataLoaderWithEFCore/GraphApi/Injector.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
using System; | ||
using System.Reflection; | ||
using GraphQL.Conventions; | ||
|
||
namespace DataLoaderWithEFCore.GraphApi | ||
{ | ||
public class Injector : IDependencyInjector | ||
{ | ||
private readonly IServiceProvider _serviceProvider; | ||
|
||
public Injector(IServiceProvider serviceProvider) | ||
{ | ||
_serviceProvider = serviceProvider; | ||
} | ||
|
||
public object Resolve(TypeInfo typeInfo) | ||
{ | ||
return _serviceProvider.GetService(typeInfo); | ||
} | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
samples/DataLoaderWithEFCore/DataLoaderWithEFCore/GraphApi/Mappings.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
using AutoMapper; | ||
using Models = DataLoaderWithEFCore.Data.Models; | ||
|
||
namespace DataLoaderWithEFCore.GraphApi | ||
{ | ||
public class Mappings : Profile | ||
{ | ||
public Mappings() | ||
{ | ||
CreateMap<Models.Actor, Schema.Actor>(); | ||
CreateMap<Models.Country, Schema.Country>(); | ||
CreateMap<Models.Movie, Schema.Movie>(); | ||
} | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
...oaderWithEFCore/DataLoaderWithEFCore/GraphApi/Schema/InputTypes/UpdateMovieTitleParams.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using System; | ||
using GraphQL.Conventions; | ||
|
||
namespace DataLoaderWithEFCore.GraphApi.Schema | ||
{ | ||
[InputType] | ||
public class UpdateMovieTitleParams | ||
{ | ||
public Guid Id { get; set; } | ||
|
||
public string NewTitle { get; set; } | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
samples/DataLoaderWithEFCore/DataLoaderWithEFCore/GraphApi/Schema/Mutation.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using System.Threading.Tasks; | ||
using AutoMapper; | ||
using DataLoaderWithEFCore.Data.Repositories; | ||
using GraphQL.Conventions; | ||
|
||
namespace DataLoaderWithEFCore.GraphApi.Schema | ||
{ | ||
public sealed class Mutation | ||
{ | ||
public async Task<Movie> UpdateMovieTitle([Inject] IMovieRepository movieRepository, UpdateMovieTitleParams @params) | ||
=> Mapper.Map<Movie>(await movieRepository.UpdateMovieTitle(@params.Id, @params.NewTitle)); | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could potentially use a project reference here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you want me to include the sample project in the main .sln file? (Only in that case a project reference would be better)