Skip to content

Commit 2a9d85f

Browse files
committed
Allow null returned for nullable query resutls
1 parent bdd935d commit 2a9d85f

30 files changed

+598
-93
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;NU1109</NoWarn>
5-
<Version>32.0.1</Version>
5+
<Version>32.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: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ partial class EfGraphQLService<TDbContext>
66
public FieldBuilder<object, TReturn> AddFirstField<TReturn>(
77
IObjectGraphType graph,
88
string name,
9-
Func<ResolveEfFieldContext<TDbContext, object>, IQueryable<TReturn>> resolve,
9+
Func<ResolveEfFieldContext<TDbContext, object>, IQueryable<TReturn>?> resolve,
1010
Func<ResolveEfFieldContext<TDbContext, object>, TReturn, Task>? mutate = null,
1111
Type? graphType = null,
1212
bool nullable = false,
@@ -22,7 +22,7 @@ public FieldBuilder<object, TReturn> AddFirstField<TReturn>(
2222
public FieldBuilder<object, TReturn> AddFirstField<TReturn>(
2323
IObjectGraphType graph,
2424
string name,
25-
Func<ResolveEfFieldContext<TDbContext, object>, Task<IQueryable<TReturn>>> resolve,
25+
Func<ResolveEfFieldContext<TDbContext, object>, Task<IQueryable<TReturn>?>?> resolve,
2626
Func<ResolveEfFieldContext<TDbContext, object>, TReturn, Task>? mutate = null,
2727
Type? graphType = null,
2828
bool nullable = false,
@@ -38,7 +38,7 @@ public FieldBuilder<object, TReturn> AddFirstField<TReturn>(
3838
public FieldBuilder<object, TReturn> AddFirstField<TReturn>(
3939
IComplexGraphType graph,
4040
string name,
41-
Func<ResolveEfFieldContext<TDbContext, object>, IQueryable<TReturn>> resolve,
41+
Func<ResolveEfFieldContext<TDbContext, object>, IQueryable<TReturn>?> resolve,
4242
Func<ResolveEfFieldContext<TDbContext, object>, TReturn, Task>? mutate = null,
4343
Type? graphType = null,
4444
bool nullable = false,
@@ -54,7 +54,7 @@ public FieldBuilder<object, TReturn> AddFirstField<TReturn>(
5454
public FieldBuilder<object, TReturn> AddFirstField<TReturn>(
5555
IComplexGraphType graph,
5656
string name,
57-
Func<ResolveEfFieldContext<TDbContext, object>, Task<IQueryable<TReturn>>> resolve,
57+
Func<ResolveEfFieldContext<TDbContext, object>, Task<IQueryable<TReturn>?>?> resolve,
5858
Func<ResolveEfFieldContext<TDbContext, object>, TReturn, Task>? mutate = null,
5959
Type? graphType = null,
6060
bool nullable = false,
@@ -70,7 +70,7 @@ public FieldBuilder<object, TReturn> AddFirstField<TReturn>(
7070
public FieldBuilder<TSource, TReturn> AddFirstField<TSource, TReturn>(
7171
IComplexGraphType graph,
7272
string name,
73-
Func<ResolveEfFieldContext<TDbContext, TSource>, IQueryable<TReturn>> resolve,
73+
Func<ResolveEfFieldContext<TDbContext, TSource>, IQueryable<TReturn>?> resolve,
7474
Func<ResolveEfFieldContext<TDbContext, TSource>, TReturn, Task>? mutate = null,
7575
Type? graphType = null,
7676
bool nullable = false,
@@ -86,7 +86,7 @@ public FieldBuilder<TSource, TReturn> AddFirstField<TSource, TReturn>(
8686
public FieldBuilder<TSource, TReturn> AddFirstField<TSource, TReturn>(
8787
IComplexGraphType graph,
8888
string name,
89-
Func<ResolveEfFieldContext<TDbContext, TSource>, Task<IQueryable<TReturn>>> resolve,
89+
Func<ResolveEfFieldContext<TDbContext, TSource>, Task<IQueryable<TReturn>?>?> resolve,
9090
Func<ResolveEfFieldContext<TDbContext, TSource>, TReturn, Task>? mutate = null,
9191
Type? graphType = null,
9292
bool nullable = false,
@@ -101,7 +101,7 @@ public FieldBuilder<TSource, TReturn> AddFirstField<TSource, TReturn>(
101101

102102
FieldType BuildFirstField<TSource, TReturn>(
103103
string name,
104-
Func<ResolveEfFieldContext<TDbContext, TSource>, IQueryable<TReturn>> resolve,
104+
Func<ResolveEfFieldContext<TDbContext, TSource>, IQueryable<TReturn>?> resolve,
105105
Func<ResolveEfFieldContext<TDbContext, TSource>, TReturn, Task>? mutate,
106106
Type? graphType,
107107
bool nullable,
@@ -123,7 +123,7 @@ FieldType BuildFirstField<TSource, TReturn>(
123123

124124
FieldType BuildFirstField<TSource, TReturn>(
125125
string name,
126-
Func<ResolveEfFieldContext<TDbContext, TSource>, Task<IQueryable<TReturn>>> resolve,
126+
Func<ResolveEfFieldContext<TDbContext, TSource>, Task<IQueryable<TReturn>?>?> resolve,
127127
Func<ResolveEfFieldContext<TDbContext, TSource>, TReturn, Task>? mutate,
128128
Type? graphType,
129129
bool nullable,
@@ -143,9 +143,20 @@ FieldType BuildFirstField<TSource, TReturn>(
143143
Type = graphType,
144144
Resolver = new FuncFieldResolver<TSource, TReturn?>(async context =>
145145
{
146-
var efFieldContext = BuildContext(context);
146+
var fieldContext = BuildContext(context);
147+
148+
var task = resolve(fieldContext);
149+
if (task == null)
150+
{
151+
return ReturnNullable();
152+
}
153+
154+
var query = await task;
155+
if (query == null)
156+
{
157+
return ReturnNullable();
158+
}
147159

148-
var query = await resolve(efFieldContext);
149160
if (disableTracking)
150161
{
151162
query = query.AsNoTracking();
@@ -187,24 +198,19 @@ FieldType BuildFirstField<TSource, TReturn>(
187198

188199
if (first is not null)
189200
{
190-
if (efFieldContext.Filters == null ||
191-
await efFieldContext.Filters.ShouldInclude(context.UserContext, efFieldContext.DbContext, context.User, first))
201+
if (fieldContext.Filters == null ||
202+
await fieldContext.Filters.ShouldInclude(context.UserContext, fieldContext.DbContext, context.User, first))
192203
{
193204
if (mutate is not null)
194205
{
195-
await mutate.Invoke(efFieldContext, first);
206+
await mutate.Invoke(fieldContext, first);
196207
}
197208

198209
return first;
199210
}
200211
}
201212

202-
if (nullable)
203-
{
204-
return null;
205-
}
206-
207-
throw new FirstEntityNotFoundException();
213+
return ReturnNullable();
208214
})
209215
};
210216

@@ -214,5 +220,8 @@ await efFieldContext.Filters.ShouldInclude(context.UserContext, efFieldContext.D
214220
}
215221

216222
return type;
223+
224+
TReturn? ReturnNullable() =>
225+
nullable ? null : throw new FirstEntityNotFoundException();
217226
}
218227
}

src/GraphQL.EntityFramework/GraphApi/EfGraphQLService_Queryable.cs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ partial class EfGraphQLService<TDbContext>
66
public FieldBuilder<object, TReturn> AddQueryField<TReturn>(
77
IComplexGraphType graph,
88
string name,
9-
Func<ResolveEfFieldContext<TDbContext, object>, IQueryable<TReturn>>? resolve = null,
9+
Func<ResolveEfFieldContext<TDbContext, object>, IQueryable<TReturn>?>? resolve = null,
1010
Type? graphType = null,
1111
bool omitQueryArguments = false)
1212
where TReturn : class
@@ -19,7 +19,7 @@ public FieldBuilder<object, TReturn> AddQueryField<TReturn>(
1919
public FieldBuilder<object, TReturn> AddQueryField<TReturn>(
2020
IComplexGraphType graph,
2121
string name,
22-
Func<ResolveEfFieldContext<TDbContext, object>, Task<IQueryable<TReturn>>>? resolve = null,
22+
Func<ResolveEfFieldContext<TDbContext, object>, Task<IQueryable<TReturn>?>?>? resolve = null,
2323
Type? graphType = null,
2424
bool omitQueryArguments = false)
2525
where TReturn : class
@@ -32,7 +32,7 @@ public FieldBuilder<object, TReturn> AddQueryField<TReturn>(
3232
public FieldBuilder<TSource, TReturn> AddQueryField<TSource, TReturn>(
3333
IComplexGraphType graph,
3434
string name,
35-
Func<ResolveEfFieldContext<TDbContext, TSource>, IQueryable<TReturn>>? resolve = null,
35+
Func<ResolveEfFieldContext<TDbContext, TSource>, IQueryable<TReturn>?>? resolve = null,
3636
Type? itemGraphType = null,
3737
bool omitQueryArguments = false)
3838
where TReturn : class
@@ -45,7 +45,7 @@ public FieldBuilder<TSource, TReturn> AddQueryField<TSource, TReturn>(
4545
public FieldBuilder<TSource, TReturn> AddQueryField<TSource, TReturn>(
4646
IComplexGraphType graph,
4747
string name,
48-
Func<ResolveEfFieldContext<TDbContext, TSource>, Task<IQueryable<TReturn>>>? resolve = null,
48+
Func<ResolveEfFieldContext<TDbContext, TSource>, Task<IQueryable<TReturn>?>?>? resolve = null,
4949
Type? itemGraphType = null,
5050
bool omitQueryArguments = false)
5151
where TReturn : class
@@ -58,7 +58,7 @@ public FieldBuilder<TSource, TReturn> AddQueryField<TSource, TReturn>(
5858
FieldType BuildQueryField<TSource, TReturn>(
5959
Type? itemGraphType,
6060
string name,
61-
Func<ResolveEfFieldContext<TDbContext, TSource>, IQueryable<TReturn>>? resolve,
61+
Func<ResolveEfFieldContext<TDbContext, TSource>, IQueryable<TReturn>?>? resolve,
6262
bool omitQueryArguments)
6363
where TReturn : class =>
6464
BuildQueryField<TSource, TReturn>(
@@ -70,7 +70,7 @@ FieldType BuildQueryField<TSource, TReturn>(
7070
FieldType BuildQueryField<TSource, TReturn>(
7171
Type? itemGraphType,
7272
string name,
73-
Func<ResolveEfFieldContext<TDbContext, TSource>, Task<IQueryable<TReturn>>>? resolve,
73+
Func<ResolveEfFieldContext<TDbContext, TSource>, Task<IQueryable<TReturn>?>?>? resolve,
7474
bool omitQueryArguments)
7575
where TReturn : class
7676
{
@@ -91,7 +91,19 @@ FieldType BuildQueryField<TSource, TReturn>(
9191
async context =>
9292
{
9393
var fieldContext = BuildContext(context);
94-
var query = await resolve(fieldContext);
94+
95+
var task = resolve(fieldContext);
96+
if (task == null)
97+
{
98+
return [];
99+
}
100+
101+
var query = await task;
102+
if (query == null)
103+
{
104+
return [];
105+
}
106+
95107
if (disableTracking)
96108
{
97109
query = query.AsNoTracking();
@@ -109,8 +121,8 @@ FieldType BuildQueryField<TSource, TReturn>(
109121

110122
try
111123
{
112-
list = await query
113-
.ToListAsync(context.CancellationToken);
124+
list = await query
125+
.ToListAsync(context.CancellationToken);
114126
}
115127
catch (TaskCanceledException)
116128
{

src/GraphQL.EntityFramework/GraphApi/EfGraphQLService_QueryableConnection.cs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ partial class EfGraphQLService<TDbContext>
99
public ConnectionBuilder<object> AddQueryConnectionField<TReturn>(
1010
IComplexGraphType graph,
1111
string name,
12-
Func<ResolveEfFieldContext<TDbContext, object>, IOrderedQueryable<TReturn>>? resolve = null,
12+
Func<ResolveEfFieldContext<TDbContext, object>, IOrderedQueryable<TReturn>?>? resolve = null,
1313
Type? itemGraphType = null,
1414
bool omitQueryArguments = false)
1515
where TReturn : class =>
@@ -23,7 +23,7 @@ public ConnectionBuilder<object> AddQueryConnectionField<TReturn>(
2323
public ConnectionBuilder<object> AddQueryConnectionField<TReturn>(
2424
IComplexGraphType graph,
2525
string name,
26-
Func<ResolveEfFieldContext<TDbContext, object>, Task<IOrderedQueryable<TReturn>>>? resolve = null,
26+
Func<ResolveEfFieldContext<TDbContext, object>, Task<IOrderedQueryable<TReturn>?>?>? resolve = null,
2727
Type? itemGraphType = null,
2828
bool omitQueryArguments = false)
2929
where TReturn : class
@@ -64,7 +64,7 @@ public ConnectionBuilder<object> AddQueryConnectionField<TReturn>(
6464
public ConnectionBuilder<TSource> AddQueryConnectionField<TSource, TReturn>(
6565
IComplexGraphType graph,
6666
string name,
67-
Func<ResolveEfFieldContext<TDbContext, TSource>, IOrderedQueryable<TReturn>>? resolve = null,
67+
Func<ResolveEfFieldContext<TDbContext, TSource>, IOrderedQueryable<TReturn>?>? resolve = null,
6868
Type? itemGraphType = null,
6969
bool omitQueryArguments = false)
7070
where TReturn : class =>
@@ -78,7 +78,7 @@ public ConnectionBuilder<TSource> AddQueryConnectionField<TSource, TReturn>(
7878
public ConnectionBuilder<TSource> AddQueryConnectionField<TSource, TReturn>(
7979
IComplexGraphType graph,
8080
string name,
81-
Func<ResolveEfFieldContext<TDbContext, TSource>, Task<IOrderedQueryable<TReturn>>>? resolve = null,
81+
Func<ResolveEfFieldContext<TDbContext, TSource>, Task<IOrderedQueryable<TReturn>?>?>? resolve = null,
8282
Type? itemGraphType = null,
8383
bool omitQueryArguments = false)
8484
where TReturn : class
@@ -121,7 +121,7 @@ public ConnectionBuilder<TSource> AddQueryConnectionField<TSource, TReturn>(
121121
ConnectionBuilder<TSource> AddQueryableConnection<TSource, TGraph, TReturn>(
122122
IComplexGraphType graph,
123123
string name,
124-
Func<ResolveEfFieldContext<TDbContext, TSource>, Task<IOrderedQueryable<TReturn>>>? resolve,
124+
Func<ResolveEfFieldContext<TDbContext, TSource>, Task<IOrderedQueryable<TReturn>?>?>? resolve,
125125
bool omitQueryArguments)
126126
where TGraph : IGraphType
127127
where TReturn : class
@@ -134,8 +134,20 @@ ConnectionBuilder<TSource> AddQueryableConnection<TSource, TGraph, TReturn>(
134134
builder.ResolveAsync(
135135
async context =>
136136
{
137-
var efFieldContext = BuildContext(context);
138-
IQueryable<TReturn> query = await resolve(efFieldContext);
137+
var fieldContext = BuildContext(context);
138+
139+
var task = resolve(fieldContext);
140+
if (task == null)
141+
{
142+
return new Connection<TSource>();
143+
}
144+
145+
IQueryable<TReturn>? query = await task;
146+
if (query == null)
147+
{
148+
return new Connection<TSource>();
149+
}
150+
139151
if (disableTracking)
140152
{
141153
query = query.AsNoTracking();
@@ -154,8 +166,8 @@ ConnectionBuilder<TSource> AddQueryableConnection<TSource, TGraph, TReturn>(
154166
context.Before!,
155167
context,
156168
context.CancellationToken,
157-
efFieldContext.Filters,
158-
efFieldContext.DbContext);
169+
fieldContext.Filters,
170+
fieldContext.DbContext);
159171
}
160172
catch (TaskCanceledException)
161173
{

0 commit comments

Comments
 (0)