10
10
using System . Collections . Generic ;
11
11
using System . ComponentModel ;
12
12
using System . ComponentModel . DataAnnotations ;
13
+ using System . ComponentModel . DataAnnotations . Schema ;
13
14
using System . Linq ;
14
15
using System . Linq . Expressions ;
15
16
using System . Reflection ;
@@ -36,6 +37,7 @@ public class SelectExpandBinderTest
36
37
private readonly SelectExpandBinder _binder ;
37
38
private readonly SelectExpandBinder _binder_lowerCamelCased ;
38
39
private readonly IQueryable < QueryCustomer > _queryable ;
40
+ private readonly IQueryable < QueryCustomer > _queryable1 ;
39
41
private readonly IQueryable < QueryCustomer > _queryable_lowerCamelCased ;
40
42
private readonly ODataQueryContext _context ;
41
43
private readonly ODataQueryContext _context_lowerCamelCased ;
@@ -82,7 +84,19 @@ public SelectExpandBinderTest()
82
84
QueryOrder order = new QueryOrder { Id = 42 , Title = "The order" , Customer = customer } ;
83
85
customer . Orders . Add ( order ) ;
84
86
87
+ QueryCustomer customer1 = new QueryCustomer
88
+ {
89
+ Orders = new List < QueryOrder > ( )
90
+ } ;
91
+
92
+ QueryOrder order1 = new QueryOrder { Id = 42 , Title = "The order" , Customer = customer1 } ;
93
+ QueryOrder order2 = null ;
94
+
95
+ customer1 . Orders . Add ( order1 ) ;
96
+ customer1 . Orders . Add ( order2 ) ;
97
+
85
98
_queryable = new [ ] { customer } . AsQueryable ( ) ;
99
+ _queryable1 = new [ ] { customer1 } . AsQueryable ( ) ;
86
100
87
101
SelectExpandQueryOption selectExpandQueryOption = new SelectExpandQueryOption ( "Orders" , expand : null , context : _context ) ;
88
102
@@ -270,7 +284,7 @@ public void Bind_UsingEFQueryProvider_GeneratedExpression__DoesNot_ContainExpand
270
284
// Act
271
285
SelectExpandBinder binder = new SelectExpandBinder ( ) ;
272
286
_queryBinderContext . QueryProvider = queryProvider ;
273
- IQueryable queryable = binder . ApplyBind ( _queryable , selectExpand . SelectExpandClause , _queryBinderContext ) ;
287
+ IQueryable queryable = binder . ApplyBind ( _queryable1 , selectExpand . SelectExpandClause , _queryBinderContext ) ;
274
288
275
289
// Assert
276
290
IEnumerator enumerator = queryable . GetEnumerator ( ) ;
@@ -282,7 +296,7 @@ public void Bind_UsingEFQueryProvider_GeneratedExpression__DoesNot_ContainExpand
282
296
IEnumerable < SelectExpandWrapper < QueryOrder > > innerOrders = partialCustomer . Container
283
297
. ToDictionary ( PropertyMapper ) [ "Orders" ] as IEnumerable < SelectExpandWrapper < QueryOrder > > ;
284
298
Assert . NotNull ( innerOrders ) ;
285
- SelectExpandWrapper < QueryOrder > partialOrder = innerOrders . Single ( ) ;
299
+ SelectExpandWrapper < QueryOrder > partialOrder = innerOrders . FirstOrDefault ( ) ;
286
300
287
301
// We only write structural properties to the instance.
288
302
// This means that navigation properties on the instance property will be null
@@ -327,7 +341,7 @@ public void Bind_UsingEFQueryProvider_LowerCamelCasedModel_GeneratedExpression__
327
341
IEnumerable < SelectExpandWrapper < QueryOrder > > innerOrders = partialCustomer . Container
328
342
. ToDictionary ( PropertyMapper ) [ "orders" ] as IEnumerable < SelectExpandWrapper < QueryOrder > > ;
329
343
Assert . NotNull ( innerOrders ) ;
330
- SelectExpandWrapper < QueryOrder > partialOrder = innerOrders . Single ( ) ;
344
+ SelectExpandWrapper < QueryOrder > partialOrder = innerOrders . FirstOrDefault ( ) ;
331
345
332
346
// We only write structural properties to the instance.
333
347
// This means that navigation properties on the instance property will be null
@@ -343,6 +357,52 @@ public void Bind_UsingEFQueryProvider_LowerCamelCasedModel_GeneratedExpression__
343
357
Assert . Null ( innerInnerCustomer . Instance . Orders ) ;
344
358
}
345
359
360
+ [ Fact ]
361
+ public void Bind_SelectAndExpand_WithNullProperties_DoesNotThrowException ( )
362
+ {
363
+ // Arrange
364
+ IQueryable < User > users ;
365
+ string expand = "FileRefNavigation" ;
366
+
367
+ User user = new User
368
+ {
369
+ UserId = 1 ,
370
+ Name = "Alex" ,
371
+ Age = 35 ,
372
+ DataFileRef = null ,
373
+ FileRefNavigation = null
374
+ } ;
375
+
376
+ users = new [ ] { user } . AsQueryable ( ) ;
377
+ ODataQueryContext context = new ODataQueryContext ( _model , typeof ( User ) ) { RequestContainer = new MockServiceProvider ( ) } ;
378
+
379
+ SelectExpandQueryOption selectExpand = new SelectExpandQueryOption ( select : null , expand : expand , context : context ) ;
380
+
381
+ QueryBinderContext queryBinderContext = new QueryBinderContext ( _model , _settings , selectExpand . Context . ElementClrType )
382
+ {
383
+ NavigationSource = context . NavigationSource
384
+ } ;
385
+
386
+ queryBinderContext . QueryProvider = HandleNullPropagationOptionHelper . EntityFrameworkQueryProviderNamespace ;
387
+
388
+ // Act
389
+ SelectExpandBinder binder = new SelectExpandBinder ( ) ;
390
+ IQueryable queryable = binder . ApplyBind ( users , selectExpand . SelectExpandClause , queryBinderContext ) ;
391
+
392
+ // Assert
393
+ Assert . NotNull ( queryable ) ;
394
+
395
+ IEnumerator enumerator = queryable . GetEnumerator ( ) ;
396
+ Assert . True ( enumerator . MoveNext ( ) ) ;
397
+ var usr = Assert . IsAssignableFrom < SelectExpandWrapper < User > > ( enumerator . Current ) ;
398
+ Assert . False ( enumerator . MoveNext ( ) ) ;
399
+ Assert . NotNull ( usr . Instance ) ;
400
+ Assert . Equal ( "Microsoft.AspNetCore.OData.Tests.Query.Expressions.User" , usr . Instance . GetType ( ) . ToString ( ) ) ;
401
+ IEnumerable < SelectExpandWrapper < DataFile > > fileRefsNavigations = usr . Container
402
+ . ToDictionary ( PropertyMapper ) [ "FileRefNavigation" ] as IEnumerable < SelectExpandWrapper < DataFile > > ;
403
+ Assert . Null ( fileRefsNavigations ) ;
404
+ }
405
+
346
406
[ Fact ]
347
407
public void Bind_GeneratedExpression_CheckNullObjectWithinChainProjectionByKey ( )
348
408
{
@@ -2082,6 +2142,7 @@ public static IEdmModel GetEdmModel()
2082
2142
builder . EntitySet < QueryOrder > ( "Orders" ) ;
2083
2143
builder . EntitySet < QueryCity > ( "Cities" ) ;
2084
2144
builder . EntitySet < QueryProduct > ( "Products" ) ;
2145
+ builder . EntitySet < User > ( "Users" ) ;
2085
2146
2086
2147
customer . Collection . Function ( "IsUpgraded" ) . Returns < bool > ( ) . Namespace = "NS" ;
2087
2148
customer . Collection . Action ( "UpgradeAll" ) . Namespace = "NS" ;
@@ -2229,9 +2290,9 @@ public class QueryCustomer
2229
2290
2230
2291
public IList < QueryAddress > Addresses { get ; set ; }
2231
2292
2232
- public QueryOrder PrivateOrder { get ; set ; }
2293
+ public QueryOrder ? PrivateOrder { get ; set ; }
2233
2294
2234
- public IList < QueryOrder > Orders { get ; set ; }
2295
+ public IList < QueryOrder > ? Orders { get ; set ; }
2235
2296
2236
2297
public List < string > TestReadonlyProperty
2237
2298
{
@@ -2292,4 +2353,27 @@ public enum QueryColor
2292
2353
2293
2354
Blue
2294
2355
}
2356
+
2357
+ public class User
2358
+ {
2359
+ [ Key ]
2360
+ public int UserId { get ; set ; }
2361
+ [ Required ]
2362
+ public string Name { get ; set ; }
2363
+ [ Required ]
2364
+ public int Age { get ; set ; }
2365
+
2366
+ //Navigations
2367
+ [ ForeignKey ( "FileRefNavigation" ) ]
2368
+ public int ? DataFileRef { get ; set ; }
2369
+ public DataFile ? FileRefNavigation { get ; set ; }
2370
+ }
2371
+
2372
+ public class DataFile
2373
+ {
2374
+ [ Key ]
2375
+ public int FileId { get ; set ; }
2376
+ [ Required ]
2377
+ public string FileName { get ; set ; }
2378
+ }
2295
2379
}
0 commit comments