Repository navigation
Expand file tree
/
Copy pathEfGraphQLConventions.cs
More file actions
106 lines (92 loc) · 4.15 KB
/
Copy pathEfGraphQLConventions.cs
File metadata and controls
106 lines (92 loc) · 4.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
namespace GraphQL.EntityFramework;
public static class EfGraphQLConventions
{
/// <summary>
/// Register the necessary services with the service provider for a data context of <typeparamref name="TDbContext"/>
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
/// <param name="resolveDbContext">A function to obtain the <typeparamref name="TDbContext"/> from the GraphQL user context. If null, then it will be extracted from the <see cref="IServiceProvider"/>.</param>
/// <param name="model">The <see cref="IModel"/> to use. If null, then it will be extracted from the <see cref="IServiceProvider"/>.</param>
/// <param name="resolveFilters">A function to obtain a list of filters to apply to the returned data. If null, then it will be extracted from the <see cref="IServiceProvider"/>.</param>
/// <param name="disableTracking">Use <see cref="EntityFrameworkQueryableExtensions.AsNoTracking{TEntity}"/> for all <see cref="IQueryable{T}"/> operations.</param>
#region RegisterInContainer
public static void RegisterInContainer<TDbContext>(
IServiceCollection services,
ResolveDbContext<TDbContext>? resolveDbContext = null,
IModel? model = null,
ResolveFilters? resolveFilters = null,
bool disableTracking = false,
bool disableAsync = false)
#endregion
where TDbContext : DbContext
{
RegisterScalarsAndArgs(services);
services.AddHttpContextAccessor();
services.AddTransient<HttpContextCapture>();
services.AddSingleton(
provider => Build(resolveDbContext, model, resolveFilters, provider, disableTracking, disableAsync));
services.AddSingleton<IEfGraphQLService<TDbContext>>(
provider => provider.GetRequiredService<EfGraphQLService<TDbContext>>());
}
static EfGraphQLService<TDbContext> Build<TDbContext>(
ResolveDbContext<TDbContext>? dbContextResolver,
IModel? model,
ResolveFilters? filters,
IServiceProvider provider,
bool disableTracking,
bool disableAsync)
where TDbContext : DbContext
{
model ??= ResolveModel<TDbContext>(provider);
filters ??= provider.GetService<ResolveFilters>();
dbContextResolver ??= _ => DbContextFromProvider<TDbContext>(provider);
return new(
model,
dbContextResolver,
filters,
disableTracking,
disableAsync);
}
static TDbContext DbContextFromProvider<TDbContext>(IServiceProvider provider)
where TDbContext : DbContext
{
var dataFromHttpContext = provider.GetService<HttpContextCapture>()?
.HttpContextAccessor
.HttpContext?
.RequestServices
.GetService<TDbContext>();
if (dataFromHttpContext is not null)
{
return dataFromHttpContext;
}
var dataFromRootProvider = provider.GetService<TDbContext>();
if (dataFromRootProvider is not null)
{
return dataFromRootProvider;
}
throw new($"Could not extract {typeof(TDbContext).Name} from the provider. Tried the HttpContext provider and the root provider.");
}
static void RegisterScalarsAndArgs(IServiceCollection services)
{
services.AddSingleton<EnumerationGraphType<StringComparison>>();
services.AddSingleton<WhereExpressionGraph>();
services.AddSingleton<OrderByGraph>();
services.AddSingleton<ComparisonGraph>();
services.AddSingleton<ConnectorGraph>();
}
static IModel ResolveModel<TDbContext>(IServiceProvider provider)
where TDbContext : DbContext
{
var model = provider.GetService<IModel>();
if (model is not null)
{
return model;
}
var dbContext = provider.GetService<TDbContext>();
if (dbContext is not null)
{
return dbContext.Model;
}
throw new($"Could not resolve {nameof(IModel)} from the {nameof(IServiceProvider)}. Tried to extract both {nameof(IModel)} and {typeof(TDbContext)}.");
}
}