|
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; |
@@ -356,6 +357,52 @@ public void Bind_UsingEFQueryProvider_LowerCamelCasedModel_GeneratedExpression__ |
356 | 357 | Assert.Null(innerInnerCustomer.Instance.Orders); |
357 | 358 | } |
358 | 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 | + |
359 | 406 | [Fact] |
360 | 407 | public void Bind_GeneratedExpression_CheckNullObjectWithinChainProjectionByKey() |
361 | 408 | { |
@@ -2095,6 +2142,7 @@ public static IEdmModel GetEdmModel() |
2095 | 2142 | builder.EntitySet<QueryOrder>("Orders"); |
2096 | 2143 | builder.EntitySet<QueryCity>("Cities"); |
2097 | 2144 | builder.EntitySet<QueryProduct>("Products"); |
| 2145 | + builder.EntitySet<User>("Users"); |
2098 | 2146 |
|
2099 | 2147 | customer.Collection.Function("IsUpgraded").Returns<bool>().Namespace="NS"; |
2100 | 2148 | customer.Collection.Action("UpgradeAll").Namespace = "NS"; |
@@ -2305,4 +2353,27 @@ public enum QueryColor |
2305 | 2353 |
|
2306 | 2354 | Blue |
2307 | 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 | + } |
2308 | 2379 | } |
0 commit comments