From 3f273b01f457af96cb7aa34a8504626f9507659d Mon Sep 17 00:00:00 2001 From: Blaise Taylor Date: Sun, 5 Jan 2025 08:55:48 -0500 Subject: [PATCH] Fix for Issue #230. ArgumentException Member does not exist. --- .../LinqExtensions.cs | 3 +-- .../AirVinylDatabaseInitializer.cs | 18 ++++++++++------ .../AirVinylData/AirVinylDbContext.cs | 1 + .../AirVinylData/Door.cs | 2 ++ .../AirVinylData/DoorKnob.cs | 11 ++++++++++ .../AirVinylModel/DoorKnobModel.cs | 11 ++++++++++ .../AirVinylModel/DoorModel.cs | 2 ++ .../ExpansionTests.cs | 21 +++++++++++++++++++ .../Mappings/AirVinylMappings.cs | 2 ++ 9 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 AutoMapper.OData.EFCore.Tests/AirVinylData/DoorKnob.cs create mode 100644 AutoMapper.OData.EFCore.Tests/AirVinylModel/DoorKnobModel.cs diff --git a/AutoMapper.AspNetCore.OData.EFCore/LinqExtensions.cs b/AutoMapper.AspNetCore.OData.EFCore/LinqExtensions.cs index efbcf27..84cf8c7 100644 --- a/AutoMapper.AspNetCore.OData.EFCore/LinqExtensions.cs +++ b/AutoMapper.AspNetCore.OData.EFCore/LinqExtensions.cs @@ -591,8 +591,7 @@ private static List> GetExpansions(this IEnumerable< ( expansions => { - segmentExpansions.Reverse(); - segmentExpansions.ForEach(exp => expansions.Insert(0, exp)); + expansions.InsertRange(0, segmentExpansions); return expansions; } ).ToList(); diff --git a/AutoMapper.OData.EFCore.Tests/AirVinylData/AirVinylDatabaseInitializer.cs b/AutoMapper.OData.EFCore.Tests/AirVinylData/AirVinylDatabaseInitializer.cs index db1c9c9..1c3ba43 100644 --- a/AutoMapper.OData.EFCore.Tests/AirVinylData/AirVinylDatabaseInitializer.cs +++ b/AutoMapper.OData.EFCore.Tests/AirVinylData/AirVinylDatabaseInitializer.cs @@ -314,9 +314,15 @@ public static void SeedDatabase(AirVinylDbContext context) new DoorManufacturer { Name = "Ikea" }, new DoorManufacturer { Name = "Hardwood" } ); + context.DoorKnobs.AddRange( + new DoorKnob { Style = "Circular" }, + new DoorKnob { Style = "Lever" } + ); + context.SaveChanges(); ICollection doorManufacturers = [.. context.DoorManufacturers]; + ICollection doorKnobs = [.. context.DoorKnobs]; context.RecordStores.AddRange( new SpecializedRecordStore() @@ -335,8 +341,8 @@ public static void SeedDatabase(AirVinylDbContext context) RoomNumbers = [3, 4, 5, 6], Doors = [ - new() { Name = "Front Door", DoorManufacturerId = doorManufacturers.Single(m => m.Name == "Serta").Id }, - new() { Name = "Side Door", DoorManufacturerId = doorManufacturers.Single(m => m.Name == "Hardwood").Id } + new() { Name = "Front Door", DoorManufacturerId = doorManufacturers.Single(m => m.Name == "Serta").Id, DoorKnobId = doorKnobs.Single(k => k.Style == "Circular").Id }, + new() { Name = "Side Door", DoorManufacturerId = doorManufacturers.Single(m => m.Name == "Hardwood").Id, DoorKnobId = doorKnobs.Single(k => k.Style == "Lever").Id } ] } }, @@ -356,8 +362,8 @@ public static void SeedDatabase(AirVinylDbContext context) RoomNumbers = [2, 3, 4, 5], Doors = [ - new() { Name = "Main Door", DoorManufacturerId = doorManufacturers.Single(m => m.Name == "Serta").Id }, - new() { Name = "Cabinet Door", DoorManufacturerId = doorManufacturers.Single(m => m.Name == "Serta").Id } + new() { Name = "Main Door", DoorManufacturerId = doorManufacturers.Single(m => m.Name == "Serta").Id, DoorKnobId = doorKnobs.Single(k => k.Style == "Circular").Id }, + new() { Name = "Cabinet Door", DoorManufacturerId = doorManufacturers.Single(m => m.Name == "Serta").Id, DoorKnobId = doorKnobs.Single(k => k.Style == "Circular").Id} ] } }, @@ -376,8 +382,8 @@ public static void SeedDatabase(AirVinylDbContext context) RoomNumbers = [1, 2, 3, 4], Doors = [ - new() { Name = "Bedroom Door", DoorManufacturerId = doorManufacturers.Single(m => m.Name == "Serta").Id }, - new() { Name = "Balcony Door", DoorManufacturerId = doorManufacturers.Single(m => m.Name == "Sealy").Id } + new() { Name = "Bedroom Door", DoorManufacturerId = doorManufacturers.Single(m => m.Name == "Serta").Id, DoorKnobId = doorKnobs.Single(k => k.Style == "Circular").Id }, + new() { Name = "Balcony Door", DoorManufacturerId = doorManufacturers.Single(m => m.Name == "Sealy").Id, DoorKnobId = doorKnobs.Single(k => k.Style == "Lever").Id} ] } } diff --git a/AutoMapper.OData.EFCore.Tests/AirVinylData/AirVinylDbContext.cs b/AutoMapper.OData.EFCore.Tests/AirVinylData/AirVinylDbContext.cs index d7bc67f..bde179a 100644 --- a/AutoMapper.OData.EFCore.Tests/AirVinylData/AirVinylDbContext.cs +++ b/AutoMapper.OData.EFCore.Tests/AirVinylData/AirVinylDbContext.cs @@ -12,6 +12,7 @@ public class AirVinylDbContext : DbContext public DbSet Ratings { get; set; } public DbSet DynamicVinylRecordProperties { get; set; } public DbSet DoorManufacturers { get; set; } + public DbSet DoorKnobs { get; set; } public AirVinylDbContext(DbContextOptions options) : base(options) diff --git a/AutoMapper.OData.EFCore.Tests/AirVinylData/Door.cs b/AutoMapper.OData.EFCore.Tests/AirVinylData/Door.cs index a33d92b..2e303c2 100644 --- a/AutoMapper.OData.EFCore.Tests/AirVinylData/Door.cs +++ b/AutoMapper.OData.EFCore.Tests/AirVinylData/Door.cs @@ -9,6 +9,8 @@ public class Door public string Name{ get; set; } public int AddressId { get; set; } public int DoorManufacturerId { get; set; } + public int DoorKnobId { get; set; } public DoorManufacturer DoorManufacturer { get; set; } + public DoorKnob DoorKnob { get; set; } } } diff --git a/AutoMapper.OData.EFCore.Tests/AirVinylData/DoorKnob.cs b/AutoMapper.OData.EFCore.Tests/AirVinylData/DoorKnob.cs new file mode 100644 index 0000000..68d2d4d --- /dev/null +++ b/AutoMapper.OData.EFCore.Tests/AirVinylData/DoorKnob.cs @@ -0,0 +1,11 @@ +using System.ComponentModel.DataAnnotations; + +namespace AutoMapper.OData.EFCore.Tests.AirVinylData +{ + public class DoorKnob + { + [Key] + public int Id { get; set; } + public string Style { get; set; } + } +} diff --git a/AutoMapper.OData.EFCore.Tests/AirVinylModel/DoorKnobModel.cs b/AutoMapper.OData.EFCore.Tests/AirVinylModel/DoorKnobModel.cs new file mode 100644 index 0000000..2e3aa71 --- /dev/null +++ b/AutoMapper.OData.EFCore.Tests/AirVinylModel/DoorKnobModel.cs @@ -0,0 +1,11 @@ +using System.ComponentModel.DataAnnotations; + +namespace AutoMapper.OData.EFCore.Tests.AirVinylModel +{ + public class DoorKnobModel + { + [Key] + public int Id { get; set; } + public string Style { get; set; } + } +} diff --git a/AutoMapper.OData.EFCore.Tests/AirVinylModel/DoorModel.cs b/AutoMapper.OData.EFCore.Tests/AirVinylModel/DoorModel.cs index 2253c0b..e299bd2 100644 --- a/AutoMapper.OData.EFCore.Tests/AirVinylModel/DoorModel.cs +++ b/AutoMapper.OData.EFCore.Tests/AirVinylModel/DoorModel.cs @@ -9,6 +9,8 @@ public class DoorModel public string Name { get; set; } public int AddressId { get; set; } public int DoorManufacturerId { get; set; } + public int DoorKnobId { get; set; } public DoorManufacturerModel DoorManufacturer { get; set; } + public DoorKnobModel DoorKnob { get; set; } } } diff --git a/AutoMapper.OData.EFCore.Tests/ExpansionTests.cs b/AutoMapper.OData.EFCore.Tests/ExpansionTests.cs index e209b30..0fcbcec 100644 --- a/AutoMapper.OData.EFCore.Tests/ExpansionTests.cs +++ b/AutoMapper.OData.EFCore.Tests/ExpansionTests.cs @@ -89,6 +89,27 @@ static void Test(ICollection collection) Assert.False(string.IsNullOrEmpty(collection.First().StoreAddress.Doors.First().Name)); Assert.NotNull(collection.First().StoreAddress.Doors.First().DoorManufacturer); Assert.False(string.IsNullOrEmpty(collection.First().StoreAddress.Doors.First().DoorManufacturer.Name)); + Assert.Null(collection.First().StoreAddress.Doors.First().DoorKnob); + } + } + + [Fact] + public async Task GetRecordStoresCanExpandMultipleNavigationPropertiesOfNavigationPropertyUnderComplexType() + { + string query = "/recordstoremodel?$expand=StoreAddress/Doors($expand=DoorManufacturer,DoorKnob)"; + Test(await GetAsync(query)); + + static void Test(ICollection collection) + { + Assert.True(collection.Count > 0); + Assert.True(collection.All(r => r.Ratings.Count == 0)); + Assert.False(string.IsNullOrEmpty(collection.First().StoreAddress.Country)); + Assert.NotEmpty(collection.First().StoreAddress.Doors); + Assert.False(string.IsNullOrEmpty(collection.First().StoreAddress.Doors.First().Name)); + Assert.NotNull(collection.First().StoreAddress.Doors.First().DoorManufacturer); + Assert.False(string.IsNullOrEmpty(collection.First().StoreAddress.Doors.First().DoorManufacturer.Name)); + Assert.NotNull(collection.First().StoreAddress.Doors.First().DoorKnob); + Assert.False(string.IsNullOrEmpty(collection.First().StoreAddress.Doors.First().DoorKnob.Style)); } } diff --git a/AutoMapper.OData.EFCore.Tests/Mappings/AirVinylMappings.cs b/AutoMapper.OData.EFCore.Tests/Mappings/AirVinylMappings.cs index d405df0..01e716a 100644 --- a/AutoMapper.OData.EFCore.Tests/Mappings/AirVinylMappings.cs +++ b/AutoMapper.OData.EFCore.Tests/Mappings/AirVinylMappings.cs @@ -11,6 +11,8 @@ public AirVinylMappings() .ForAllMembers(o => o.ExplicitExpansion()); CreateMap() .ForAllMembers(o => o.ExplicitExpansion()); + CreateMap() + .ForAllMembers(o => o.ExplicitExpansion()); CreateMap() .ForAllMembers(o => o.ExplicitExpansion()); CreateMap()