Skip to content

Commit 88088ae

Browse files
committed
add Task based resolve
1 parent 6aa6d91 commit 88088ae

12 files changed

+428
-67
lines changed

src/Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<Project>
33
<PropertyGroup>
44
<NoWarn>CS1591;NU5104;CS1573;CS9107;NU1608</NoWarn>
5-
<Version>28.0.0</Version>
5+
<Version>28.1.0</Version>
66
<LangVersion>preview</LangVersion>
77
<AssemblyVersion>1.0.0</AssemblyVersion>
88
<PackageTags>EntityFrameworkCore, EntityFramework, GraphQL</PackageTags>

src/GraphQL.EntityFramework/GraphApi/EfGraphQLService_First.cs

Lines changed: 128 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,22 @@ public FieldBuilder<object, TReturn> AddFirstField<TReturn>(
1919
return new FieldBuilderEx<object, TReturn>(field);
2020
}
2121

22+
public FieldBuilder<object, TReturn> AddFirstField<TReturn>(
23+
IObjectGraphType graph,
24+
string name,
25+
Func<ResolveEfFieldContext<TDbContext, object>, Task<IQueryable<TReturn>>> resolve,
26+
Func<ResolveEfFieldContext<TDbContext, object>, TReturn, Task>? mutate = null,
27+
Type? graphType = null,
28+
bool nullable = false,
29+
bool omitQueryArguments = false,
30+
bool idOnly = false)
31+
where TReturn : class
32+
{
33+
var field = BuildFirstField(name, resolve, mutate, graphType, nullable, omitQueryArguments, idOnly);
34+
graph.AddField(field);
35+
return new FieldBuilderEx<object, TReturn>(field);
36+
}
37+
2238
public FieldBuilder<object, TReturn> AddFirstField<TReturn>(
2339
IComplexGraphType graph,
2440
string name,
@@ -35,6 +51,22 @@ public FieldBuilder<object, TReturn> AddFirstField<TReturn>(
3551
return new FieldBuilderEx<object, TReturn>(field);
3652
}
3753

54+
public FieldBuilder<object, TReturn> AddFirstField<TReturn>(
55+
IComplexGraphType graph,
56+
string name,
57+
Func<ResolveEfFieldContext<TDbContext, object>, Task<IQueryable<TReturn>>> resolve,
58+
Func<ResolveEfFieldContext<TDbContext, object>, TReturn, Task>? mutate = null,
59+
Type? graphType = null,
60+
bool nullable = false,
61+
bool omitQueryArguments = false,
62+
bool idOnly = false)
63+
where TReturn : class
64+
{
65+
var field = BuildFirstField(name, resolve, mutate, graphType, nullable, omitQueryArguments, idOnly);
66+
graph.AddField(field);
67+
return new FieldBuilderEx<object, TReturn>(field);
68+
}
69+
3870
public FieldBuilder<TSource, TReturn> AddFirstField<TSource, TReturn>(
3971
IComplexGraphType graph,
4072
string name,
@@ -51,6 +83,22 @@ public FieldBuilder<TSource, TReturn> AddFirstField<TSource, TReturn>(
5183
return new FieldBuilderEx<TSource, TReturn>(field);
5284
}
5385

86+
public FieldBuilder<TSource, TReturn> AddFirstField<TSource, TReturn>(
87+
IComplexGraphType graph,
88+
string name,
89+
Func<ResolveEfFieldContext<TDbContext, TSource>, Task<IQueryable<TReturn>>> resolve,
90+
Func<ResolveEfFieldContext<TDbContext, TSource>, TReturn, Task>? mutate = null,
91+
Type? graphType = null,
92+
bool nullable = false,
93+
bool omitQueryArguments = false,
94+
bool idOnly = false)
95+
where TReturn : class
96+
{
97+
var field = BuildFirstField(name, resolve, mutate, graphType, nullable, omitQueryArguments, idOnly);
98+
graph.AddField(field);
99+
return new FieldBuilderEx<TSource, TReturn>(field);
100+
}
101+
54102
FieldType BuildFirstField<TSource, TReturn>(
55103
string name,
56104
Func<ResolveEfFieldContext<TDbContext, TSource>, IQueryable<TReturn>> resolve,
@@ -60,6 +108,28 @@ FieldType BuildFirstField<TSource, TReturn>(
60108
bool omitQueryArguments,
61109
bool idOnly)
62110
where TReturn : class
111+
=> BuildFirstField(
112+
name,
113+
_ =>
114+
{
115+
var queryable = resolve(_);
116+
return Task.FromResult(queryable);
117+
},
118+
mutate,
119+
graphType,
120+
nullable,
121+
omitQueryArguments,
122+
idOnly);
123+
124+
FieldType BuildFirstField<TSource, TReturn>(
125+
string name,
126+
Func<ResolveEfFieldContext<TDbContext, TSource>, Task<IQueryable<TReturn>>> resolve,
127+
Func<ResolveEfFieldContext<TDbContext, TSource>, TReturn, Task>? mutate,
128+
Type? graphType,
129+
bool nullable,
130+
bool omitQueryArguments,
131+
bool idOnly)
132+
where TReturn : class
63133
{
64134
Guard.AgainstWhiteSpace(nameof(name), name);
65135

@@ -71,79 +141,78 @@ FieldType BuildFirstField<TSource, TReturn>(
71141
{
72142
Name = name,
73143
Type = graphType,
74-
Resolver = new FuncFieldResolver<TSource, TReturn?>(
75-
async context =>
76-
{
77-
var efFieldContext = BuildContext(context);
144+
Resolver = new FuncFieldResolver<TSource, TReturn?>(async context =>
145+
{
146+
var efFieldContext = BuildContext(context);
78147

79-
var query = resolve(efFieldContext);
80-
if (disableTracking)
81-
{
82-
query = query.AsNoTracking();
83-
}
148+
var query = await resolve(efFieldContext);
149+
if (disableTracking)
150+
{
151+
query = query.AsNoTracking();
152+
}
84153

85-
query = includeAppender.AddIncludes(query, context);
86-
query = query.ApplyGraphQlArguments(context, names, false, omitQueryArguments);
154+
query = includeAppender.AddIncludes(query, context);
155+
query = query.ApplyGraphQlArguments(context, names, false, omitQueryArguments);
87156

88-
QueryLogger.Write(query);
157+
QueryLogger.Write(query);
89158

90-
TReturn? first;
91-
try
92-
{
93-
if (disableAsync)
94-
{
95-
first = query.FirstOrDefault();
96-
}
97-
else
98-
{
99-
first = await query.FirstOrDefaultAsync(context.CancellationToken);
100-
}
101-
}
102-
catch (TaskCanceledException)
103-
{
104-
throw;
105-
}
106-
catch (OperationCanceledException)
159+
TReturn? first;
160+
try
161+
{
162+
if (disableAsync)
107163
{
108-
throw;
164+
first = query.FirstOrDefault();
109165
}
110-
catch (Exception exception)
166+
else
111167
{
112-
throw new(
113-
$"""
114-
Failed to execute query for field `{name}`
115-
GraphType: {graphType.FullName}
116-
TSource: {typeof(TSource).FullName}
117-
TReturn: {typeof(TReturn).FullName}
118-
DisableAsync: {disableAsync}
119-
OmitQueryArguments: {omitQueryArguments}
120-
Nullable: {nullable}
121-
KeyNames: {JoinKeys(names)}
122-
Query: {query.ToQueryString()}
123-
""",
124-
exception);
168+
first = await query.FirstOrDefaultAsync(context.CancellationToken);
125169
}
126-
127-
if (first is not null)
170+
}
171+
catch (TaskCanceledException)
172+
{
173+
throw;
174+
}
175+
catch (OperationCanceledException)
176+
{
177+
throw;
178+
}
179+
catch (Exception exception)
180+
{
181+
throw new(
182+
$"""
183+
Failed to execute query for field `{name}`
184+
GraphType: {graphType.FullName}
185+
TSource: {typeof(TSource).FullName}
186+
TReturn: {typeof(TReturn).FullName}
187+
DisableAsync: {disableAsync}
188+
OmitQueryArguments: {omitQueryArguments}
189+
Nullable: {nullable}
190+
KeyNames: {JoinKeys(names)}
191+
Query: {query.ToQueryString()}
192+
""",
193+
exception);
194+
}
195+
196+
if (first is not null)
197+
{
198+
if (await efFieldContext.Filters.ShouldInclude(context.UserContext, context.User, first))
128199
{
129-
if (await efFieldContext.Filters.ShouldInclude(context.UserContext, context.User, first))
200+
if (mutate is not null)
130201
{
131-
if (mutate is not null)
132-
{
133-
await mutate.Invoke(efFieldContext, first);
134-
}
135-
136-
return first;
202+
await mutate.Invoke(efFieldContext, first);
137203
}
138-
}
139204

140-
if (nullable)
141-
{
142-
return null;
205+
return first;
143206
}
207+
}
208+
209+
if (nullable)
210+
{
211+
return null;
212+
}
144213

145-
throw new FirstEntityNotFoundException();
146-
})
214+
throw new FirstEntityNotFoundException();
215+
})
147216
};
148217

149218
if (!omitQueryArguments)

src/GraphQL.EntityFramework/GraphApi/EfGraphQLService_Queryable.cs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,19 @@ public FieldBuilder<object, TReturn> AddQueryField<TReturn>(
1616
return new FieldBuilderEx<object, TReturn>(field);
1717
}
1818

19+
public FieldBuilder<object, TReturn> AddQueryField<TReturn>(
20+
IComplexGraphType graph,
21+
string name,
22+
Func<ResolveEfFieldContext<TDbContext, object>, Task<IQueryable<TReturn>>>? resolve = null,
23+
Type? graphType = null,
24+
bool omitQueryArguments = false)
25+
where TReturn : class
26+
{
27+
var field = BuildQueryField(graphType, name, resolve, omitQueryArguments);
28+
graph.AddField(field);
29+
return new FieldBuilderEx<object, TReturn>(field);
30+
}
31+
1932
public FieldBuilder<TSource, TReturn> AddQueryField<TSource, TReturn>(
2033
IComplexGraphType graph,
2134
string name,
@@ -29,11 +42,36 @@ public FieldBuilder<TSource, TReturn> AddQueryField<TSource, TReturn>(
2942
return new FieldBuilderEx<TSource, TReturn>(field);
3043
}
3144

45+
public FieldBuilder<TSource, TReturn> AddQueryField<TSource, TReturn>(
46+
IComplexGraphType graph,
47+
string name,
48+
Func<ResolveEfFieldContext<TDbContext, TSource>, Task<IQueryable<TReturn>>>? resolve = null,
49+
Type? itemGraphType = null,
50+
bool omitQueryArguments = false)
51+
where TReturn : class
52+
{
53+
var field = BuildQueryField(itemGraphType, name, resolve, omitQueryArguments);
54+
graph.AddField(field);
55+
return new FieldBuilderEx<TSource, TReturn>(field);
56+
}
57+
3258
FieldType BuildQueryField<TSource, TReturn>(
3359
Type? itemGraphType,
3460
string name,
3561
Func<ResolveEfFieldContext<TDbContext, TSource>, IQueryable<TReturn>>? resolve,
3662
bool omitQueryArguments)
63+
where TReturn : class =>
64+
BuildQueryField<TSource, TReturn>(
65+
itemGraphType,
66+
name,
67+
resolve == null ? null : context => Task.FromResult(resolve(context)),
68+
omitQueryArguments);
69+
70+
FieldType BuildQueryField<TSource, TReturn>(
71+
Type? itemGraphType,
72+
string name,
73+
Func<ResolveEfFieldContext<TDbContext, TSource>, Task<IQueryable<TReturn>>>? resolve,
74+
bool omitQueryArguments)
3775
where TReturn : class
3876
{
3977
Guard.AgainstWhiteSpace(nameof(name), name);
@@ -53,7 +91,7 @@ FieldType BuildQueryField<TSource, TReturn>(
5391
async context =>
5492
{
5593
var fieldContext = BuildContext(context);
56-
var query = resolve(fieldContext);
94+
var query = await resolve(fieldContext);
5795
if (disableTracking)
5896
{
5997
query = query.AsNoTracking();

src/GraphQL.EntityFramework/GraphApi/EfGraphQLService_QueryableConnection.cs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,20 @@ public ConnectionBuilder<object> AddQueryConnectionField<TReturn>(
1212
Func<ResolveEfFieldContext<TDbContext, object>, IOrderedQueryable<TReturn>>? resolve = null,
1313
Type? itemGraphType = null,
1414
bool omitQueryArguments = false)
15+
where TReturn : class =>
16+
AddQueryConnectionField<TReturn>(
17+
graph,
18+
name,
19+
resolve == null ? null : context => Task.FromResult(resolve(context)),
20+
itemGraphType,
21+
omitQueryArguments);
22+
23+
public ConnectionBuilder<object> AddQueryConnectionField<TReturn>(
24+
IComplexGraphType graph,
25+
string name,
26+
Func<ResolveEfFieldContext<TDbContext, object>, Task<IOrderedQueryable<TReturn>>>? resolve = null,
27+
Type? itemGraphType = null,
28+
bool omitQueryArguments = false)
1529
where TReturn : class
1630
{
1731
itemGraphType ??= GraphTypeFinder.FindGraphType<TReturn>();
@@ -54,6 +68,20 @@ public ConnectionBuilder<TSource> AddQueryConnectionField<TSource, TReturn>(
5468
Func<ResolveEfFieldContext<TDbContext, TSource>, IOrderedQueryable<TReturn>>? resolve = null,
5569
Type? itemGraphType = null,
5670
bool omitQueryArguments = false)
71+
where TReturn : class =>
72+
AddQueryConnectionField<TSource, TReturn>(
73+
graph,
74+
name,
75+
resolve == null ? null : context => Task.FromResult(resolve(context)),
76+
itemGraphType,
77+
omitQueryArguments);
78+
79+
public ConnectionBuilder<TSource> AddQueryConnectionField<TSource, TReturn>(
80+
IComplexGraphType graph,
81+
string name,
82+
Func<ResolveEfFieldContext<TDbContext, TSource>, Task<IOrderedQueryable<TReturn>>>? resolve = null,
83+
Type? itemGraphType = null,
84+
bool omitQueryArguments = false)
5785
where TReturn : class
5886
{
5987
itemGraphType ??= GraphTypeFinder.FindGraphType<TReturn>();
@@ -95,7 +123,7 @@ public ConnectionBuilder<TSource> AddQueryConnectionField<TSource, TReturn>(
95123
ConnectionBuilder<TSource> AddQueryableConnection<TSource, TGraph, TReturn>(
96124
IComplexGraphType graph,
97125
string name,
98-
Func<ResolveEfFieldContext<TDbContext, TSource>, IQueryable<TReturn>>? resolve,
126+
Func<ResolveEfFieldContext<TDbContext, TSource>, Task<IOrderedQueryable<TReturn>>>? resolve,
99127
bool omitQueryArguments)
100128
where TGraph : IGraphType
101129
where TReturn : class
@@ -109,7 +137,7 @@ ConnectionBuilder<TSource> AddQueryableConnection<TSource, TGraph, TReturn>(
109137
async context =>
110138
{
111139
var efFieldContext = BuildContext(context);
112-
var query = resolve(efFieldContext);
140+
IQueryable<TReturn> query = await resolve(efFieldContext);
113141
if (disableTracking)
114142
{
115143
query = query.AsNoTracking();

0 commit comments

Comments
 (0)