diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6a4770100e..9f44f8bcdc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,6 +17,9 @@ jobs: uses: actions/checkout@v2 with: fetch-depth: 0 + - name: Install SQL Local DB + run: ./Setup.ps1 + shell: pwsh - name: Build and Test run: ./Build.ps1 shell: pwsh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4aa4761ef3..8f864af155 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,6 +14,9 @@ jobs: uses: actions/checkout@v2 with: fetch-depth: 0 + - name: Install SQL Local DB + run: ./Setup.ps1 + shell: pwsh - name: Build and Test run: ./Build.ps1 shell: pwsh diff --git a/AutoMapper.sln b/AutoMapper.sln index e57553e109..194e366c0c 100644 --- a/AutoMapper.sln +++ b/AutoMapper.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29215.179 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.32002.185 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0691ABF2-B3C7-43BF-9862-2D8D1299CE58}" ProjectSection(SolutionItems) = preProject @@ -14,6 +14,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Push.ps1 = Push.ps1 README.md = README.md .github\workflows\release.yml = .github\workflows\release.yml + Setup.ps1 = Setup.ps1 EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmark", "src\Benchmark\Benchmark.csproj", "{B8051389-CB47-46FB-B234-9D49506704AA}" diff --git a/Setup.ps1 b/Setup.ps1 new file mode 100644 index 0000000000..a20035ad42 --- /dev/null +++ b/Setup.ps1 @@ -0,0 +1,32 @@ +# Taken from psake https://github.com/psake/psake + +<# +.SYNOPSIS + This is a helper function that runs a scriptblock and checks the PS variable $lastexitcode + to see if an error occcured. If an error is detected then an exception is thrown. + This function allows you to run command-line programs without having to + explicitly check the $lastexitcode variable. +.EXAMPLE + exec { svn info $repository_trunk } "Error executing SVN. Please verify SVN command-line client is installed" +#> +function Exec +{ + [CmdletBinding()] + param( + [Parameter(Position=0,Mandatory=1)][scriptblock]$cmd, + [Parameter(Position=1,Mandatory=0)][string]$errorMessage = ($msgs.error_bad_command -f $cmd) + ) + & $cmd + if ($lastexitcode -ne 0) { + throw ("Exec: " + $errorMessage) + } +} + +Write-Host "Downloading" +Import-Module BitsTransfer +Start-BitsTransfer -Source https://download.microsoft.com/download/7/c/1/7c14e92e-bdcb-4f89-b7cf-93543e7112d1/SqlLocalDB.msi -Destination SqlLocalDB.msi +Write-Host "Installing" +Start-Process -FilePath "SqlLocalDB.msi" -Wait -ArgumentList "/qn", "/norestart", "/l*v SqlLocalDBInstall.log", "IACCEPTSQLLOCALDBLICENSETERMS=YES"; +Write-Host "Checking" +sqlcmd -l 60 -S "(localdb)\MSSQLLocalDB" -Q "SELECT @@VERSION;" + diff --git a/src/IntegrationTests/App.config b/src/IntegrationTests/App.config deleted file mode 100644 index b63cdc70ad..0000000000 --- a/src/IntegrationTests/App.config +++ /dev/null @@ -1,20 +0,0 @@ - - - - -
- - - - - - - - - - - \ No newline at end of file diff --git a/src/IntegrationTests/AutoMapper.IntegrationTests.csproj b/src/IntegrationTests/AutoMapper.IntegrationTests.csproj index da830e1022..89294efffa 100644 --- a/src/IntegrationTests/AutoMapper.IntegrationTests.csproj +++ b/src/IntegrationTests/AutoMapper.IntegrationTests.csproj @@ -11,7 +11,7 @@ - + diff --git a/src/IntegrationTests/BuiltInTypes/ByteArray.cs b/src/IntegrationTests/BuiltInTypes/ByteArray.cs index 8c0c8c6708..1b54202cef 100644 --- a/src/IntegrationTests/BuiltInTypes/ByteArray.cs +++ b/src/IntegrationTests/BuiltInTypes/ByteArray.cs @@ -1,75 +1,76 @@ using System.ComponentModel.DataAnnotations; -using System.Data.Entity; using System.Linq; +using System.Threading.Tasks; +using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; using Shouldly; using Xunit; -namespace AutoMapper.IntegrationTests +namespace AutoMapper.IntegrationTests.BuiltInTypes; + +public class ByteArrayColumns : AutoMapperSpecBase, IAsyncLifetime { - using UnitTests; - using QueryableExtensions; - - public class ByteArrayColumns : AutoMapperSpecBase + public class Customer { - public class Customer - { - [Key] - public int Id { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - - public byte[] RowVersion { get; set; } - } + [Key] + public int Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } - public class CustomerViewModel - { - public string FirstName { get; set; } - public string LastName { get; set; } - public byte[] RowVersion { get; set; } - } + public byte[] RowVersion { get; set; } + } - public class Context : DbContext - { - public Context() - { - Database.SetInitializer(new DatabaseInitializer()); - } + public class CustomerViewModel + { + public string FirstName { get; set; } + public string LastName { get; set; } + public byte[] RowVersion { get; set; } + } - public DbSet Customers { get; set; } - } + public class Context : LocalDbContext + { + public DbSet Customers { get; set; } + } - public class DatabaseInitializer : CreateDatabaseIfNotExists + public class DatabaseInitializer : CreateDatabaseIfNotExists + { + protected override void Seed(Context context) { - protected override void Seed(Context context) + context.Customers.Add(new Customer { - context.Customers.Add(new Customer - { - Id = 1, - FirstName = "Bob", - LastName = "Smith", - RowVersion = new byte[] { 1, 2, 3 } - }); + FirstName = "Bob", + LastName = "Smith", + RowVersion = new byte[] { 1, 2, 3 } + }); - base.Seed(context); - } + base.Seed(context); } + } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection(); - }); + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection(); + }); - [Fact] - public void Can_map_with_projection() + [Fact] + public void Can_map_with_projection() + { + using (var context = new Context()) { - using (var context = new Context()) + var customerVms = ProjectTo(context.Customers).ToList(); + customerVms.ForEach(x => { - var customerVms = ProjectTo(context.Customers).ToList(); - customerVms.ForEach(x => - { - x.RowVersion.SequenceEqual(new byte[] { 1, 2, 3 }).ShouldBeTrue(); - }); - } + x.RowVersion.SequenceEqual(new byte[] { 1, 2, 3 }).ShouldBeTrue(); + }); } } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/BuiltInTypes/DateTimeToNullableDateTime.cs b/src/IntegrationTests/BuiltInTypes/DateTimeToNullableDateTime.cs index 69988a2e63..8eef1e3df3 100644 --- a/src/IntegrationTests/BuiltInTypes/DateTimeToNullableDateTime.cs +++ b/src/IntegrationTests/BuiltInTypes/DateTimeToNullableDateTime.cs @@ -1,46 +1,57 @@ -using Shouldly; -using System; -using System.Data.Entity; +using System; using System.Linq; +using System.Threading.Tasks; +using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; +using Shouldly; using Xunit; -namespace AutoMapper.UnitTests.Projection +namespace AutoMapper.IntegrationTests.BuiltInTypes; + +public class DateTimeToNullableDateTime : AutoMapperSpecBase, IAsyncLifetime { - public class DateTimeToNullableDateTime : AutoMapperSpecBase + public class Parent { - public class Parent - { - public int Id { get; set; } - public int Value { get; set; } + public int Id { get; set; } + public int Value { get; set; } - } - public class ParentDto - { - public int? Value { get; set; } - public DateTime? Date { get; set; } - } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - cfg.CreateProjection().ForMember(dto => dto.Date, opt => opt.MapFrom(src => DateTime.MaxValue))); - public class TestContext : DbContext - { - public TestContext(): base() => Database.SetInitializer(new DatabaseInitializer()); - public DbSet Parents { get; set; } - } - public class DatabaseInitializer : DropCreateDatabaseAlways + } + public class ParentDto + { + public int? Value { get; set; } + public DateTime? Date { get; set; } + } + + private readonly DateTime _expected = new(2000, 1, 1); + protected override MapperConfiguration CreateConfiguration() => new(cfg => + cfg.CreateProjection().ForMember(dto => dto.Date, opt => opt.MapFrom(src => _expected))); + public class TestContext : LocalDbContext + { + public DbSet Parents { get; set; } + } + public class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(TestContext testContext) { - protected override void Seed(TestContext testContext) - { - testContext.Parents.Add(new Parent{ Value = 5 }); - base.Seed(testContext); - } + testContext.Parents.Add(new Parent{ Value = 5 }); + base.Seed(testContext); } - [Fact] - public void Should_not_fail() + } + [Fact] + public void Should_not_fail() + { + using (var context = new TestContext()) { - using (var context = new TestContext()) - { - ProjectTo(context.Parents).Single().Date.ShouldBe(DateTime.MaxValue); - } + ProjectTo(context.Parents).Single().Date.ShouldBe(_expected); } } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/BuiltInTypes/Enums.cs b/src/IntegrationTests/BuiltInTypes/Enums.cs index d1b7a9ce0b..b1341aebf3 100644 --- a/src/IntegrationTests/BuiltInTypes/Enums.cs +++ b/src/IntegrationTests/BuiltInTypes/Enums.cs @@ -1,126 +1,148 @@ -using System.ComponentModel.DataAnnotations; -using System.Data.Entity; +using System; using System.Linq; +using System.Threading.Tasks; +using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; using Shouldly; using Xunit; -namespace AutoMapper.IntegrationTests -{ - using System; - using UnitTests; +namespace AutoMapper.IntegrationTests.BuiltInTypes; - public class EnumToUnderlyingType : AutoMapperSpecBase +public class EnumToUnderlyingType : AutoMapperSpecBase, IAsyncLifetime +{ + public class Customer { - public class Customer - { - public int Id { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - public ConsoleColor ConsoleColor { get; set; } - } - public class CustomerViewModel - { - public string FirstName { get; set; } - public string LastName { get; set; } - public int ConsoleColor { get; set; } - } - public class Context : DbContext - { - public Context() => Database.SetInitializer(new DatabaseInitializer()); - public DbSet Customers { get; set; } - } - public class DatabaseInitializer : CreateDatabaseIfNotExists - { - protected override void Seed(Context context) - { - context.Customers.Add(new Customer { Id = 1, FirstName = "Bob", LastName = "Smith", ConsoleColor = ConsoleColor.Yellow }); - base.Seed(context); - } - } - protected override MapperConfiguration CreateConfiguration() => new(cfg => cfg.CreateProjection()); - [Fact] - public void Can_map_with_projection() - { - using (var context = new Context()) - { - ProjectTo(context.Customers).First().ConsoleColor.ShouldBe((int)ConsoleColor.Yellow); - } - } + public int Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + public ConsoleColor ConsoleColor { get; set; } } - public class UnderlyingTypeToEnum : AutoMapperSpecBase + public class CustomerViewModel { - public class Customer - { - public int Id { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - public int ConsoleColor { get; set; } - } - public class CustomerViewModel - { - public string FirstName { get; set; } - public string LastName { get; set; } - public ConsoleColor ConsoleColor { get; set; } - } - public class Context : DbContext - { - public Context() => Database.SetInitializer(new DatabaseInitializer()); - public DbSet Customers { get; set; } - } - public class DatabaseInitializer : CreateDatabaseIfNotExists - { - protected override void Seed(Context context) - { - context.Customers.Add(new Customer { Id = 1, FirstName = "Bob", LastName = "Smith", ConsoleColor = (int)ConsoleColor.Yellow }); - base.Seed(context); - } - } - protected override MapperConfiguration CreateConfiguration() => new(cfg => cfg.CreateProjection()); - [Fact] - public void Can_map_with_projection() + public string FirstName { get; set; } + public string LastName { get; set; } + public int ConsoleColor { get; set; } + } + public class Context : LocalDbContext + { + public DbSet Customers { get; set; } + } + public class DatabaseInitializer : CreateDatabaseIfNotExists + { + protected override void Seed(Context context) { - using (var context = new Context()) - { - ProjectTo(context.Customers).First().ConsoleColor.ShouldBe(ConsoleColor.Yellow); - } + context.Customers.Add(new Customer { FirstName = "Bob", LastName = "Smith", ConsoleColor = ConsoleColor.Yellow }); + base.Seed(context); } } - public class EnumToEnum : AutoMapperSpecBase + protected override MapperConfiguration CreateConfiguration() => new(cfg => cfg.CreateProjection()); + [Fact] + public void Can_map_with_projection() { - public class Customer + using (var context = new Context()) { - public int Id { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - public DayOfWeek ConsoleColor { get; set; } + ProjectTo(context.Customers).First().ConsoleColor.ShouldBe((int)ConsoleColor.Yellow); } - public class CustomerViewModel + } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; +} +public class UnderlyingTypeToEnum : AutoMapperSpecBase, IAsyncLifetime +{ + public class Customer + { + public int Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + public int ConsoleColor { get; set; } + } + public class CustomerViewModel + { + public string FirstName { get; set; } + public string LastName { get; set; } + public ConsoleColor ConsoleColor { get; set; } + } + public class Context : LocalDbContext + { + public DbSet Customers { get; set; } + } + public class DatabaseInitializer : CreateDatabaseIfNotExists + { + protected override void Seed(Context context) { - public string FirstName { get; set; } - public string LastName { get; set; } - public ConsoleColor ConsoleColor { get; set; } + context.Customers.Add(new Customer { FirstName = "Bob", LastName = "Smith", ConsoleColor = (int)ConsoleColor.Yellow }); + base.Seed(context); } - public class Context : DbContext + } + protected override MapperConfiguration CreateConfiguration() => new(cfg => cfg.CreateProjection()); + [Fact] + public void Can_map_with_projection() + { + using (var context = new Context()) { - public Context() => Database.SetInitializer(new DatabaseInitializer()); - public DbSet Customers { get; set; } + ProjectTo(context.Customers).First().ConsoleColor.ShouldBe(ConsoleColor.Yellow); } - public class DatabaseInitializer : CreateDatabaseIfNotExists + } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; +} +public class EnumToEnum : AutoMapperSpecBase, IAsyncLifetime +{ + public class Customer + { + public int Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + public DayOfWeek ConsoleColor { get; set; } + } + public class CustomerViewModel + { + public string FirstName { get; set; } + public string LastName { get; set; } + public ConsoleColor ConsoleColor { get; set; } + } + public class Context : LocalDbContext + { + public DbSet Customers { get; set; } + } + public class DatabaseInitializer : CreateDatabaseIfNotExists + { + protected override void Seed(Context context) { - protected override void Seed(Context context) - { - context.Customers.Add(new Customer { Id = 1, FirstName = "Bob", LastName = "Smith", ConsoleColor = DayOfWeek.Saturday }); - base.Seed(context); - } + context.Customers.Add(new Customer { FirstName = "Bob", LastName = "Smith", ConsoleColor = DayOfWeek.Saturday }); + base.Seed(context); } - protected override MapperConfiguration CreateConfiguration() => new(cfg => cfg.CreateProjection()); - [Fact] - public void Can_map_with_projection() + } + protected override MapperConfiguration CreateConfiguration() => new(cfg => cfg.CreateProjection()); + [Fact] + public void Can_map_with_projection() + { + using (var context = new Context()) { - using (var context = new Context()) - { - ProjectTo(context.Customers).First().ConsoleColor.ShouldBe(ConsoleColor.DarkYellow); - } + ProjectTo(context.Customers).First().ConsoleColor.ShouldBe(ConsoleColor.DarkYellow); } } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/BuiltInTypes/NullableToNonNullable.cs b/src/IntegrationTests/BuiltInTypes/NullableToNonNullable.cs index fe8a8dc96d..0a87132917 100644 --- a/src/IntegrationTests/BuiltInTypes/NullableToNonNullable.cs +++ b/src/IntegrationTests/BuiltInTypes/NullableToNonNullable.cs @@ -1,131 +1,135 @@ using System.ComponentModel.DataAnnotations; -using System.Data.Entity; using System.Linq; +using System.Threading.Tasks; +using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; using Shouldly; using Xunit; -namespace AutoMapper.IntegrationTests +namespace AutoMapper.IntegrationTests.BuiltInTypes; + +public class NullableLongToLong : AutoMapperSpecBase, IAsyncLifetime { - using UnitTests; - using QueryableExtensions; - - public class NullableLongToLong : AutoMapperSpecBase + public class Customer { - public class Customer - { - [Key] - public long? Id { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - } + [Key] + public long? Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + } - public class CustomerViewModel - { - public long Id { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - } + public class CustomerViewModel + { + public long Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + } + + public class Context : LocalDbContext + { + public DbSet Customers { get; set; } + } - public class Context : DbContext + public class DatabaseInitializer : CreateDatabaseIfNotExists + { + protected override void Seed(Context context) { - public Context() + context.Customers.Add(new Customer { - Database.SetInitializer(new DatabaseInitializer()); - } + FirstName = "Bob", + LastName = "Smith", + }); - public DbSet Customers { get; set; } + base.Seed(context); } + } + + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection(); + }); - public class DatabaseInitializer : CreateDatabaseIfNotExists + [Fact] + public void Can_map_with_projection() + { + using (var context = new Context()) { - protected override void Seed(Context context) - { - context.Customers.Add(new Customer - { - Id = 1, - FirstName = "Bob", - LastName = "Smith", - }); - - base.Seed(context); - } + var model = ProjectTo(context.Customers).Single(); + model.Id.ShouldBe(1); + model.FirstName.ShouldBe("Bob"); + model.LastName.ShouldBe("Smith"); } + } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection(); - }); + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); - [Fact] - public void Can_map_with_projection() - { - using (var context = new Context()) - { - var model = ProjectTo(context.Customers).Single(); - model.Id.ShouldBe(1); - model.FirstName.ShouldBe("Bob"); - model.LastName.ShouldBe("Smith"); - } - } + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; +} + +public class NullableIntToLong : AutoMapperSpecBase, IAsyncLifetime +{ + public class Customer + { + [Key] + public int? Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } } - public class NullableIntToLong : AutoMapperSpecBase + public class CustomerViewModel { - public class Customer - { - [Key] - public int? Id { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - } + public long Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + } - public class CustomerViewModel - { - public long Id { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - } + public class Context : LocalDbContext + { + public DbSet Customers { get; set; } + } - public class Context : DbContext + public class DatabaseInitializer : CreateDatabaseIfNotExists + { + protected override void Seed(Context context) { - public Context() + context.Customers.Add(new Customer { - Database.SetInitializer(new DatabaseInitializer()); - } + FirstName = "Bob", + LastName = "Smith", + }); - public DbSet Customers { get; set; } + base.Seed(context); } + } + + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection(); + }); - public class DatabaseInitializer : CreateDatabaseIfNotExists + [Fact] + public void Can_map_with_projection() + { + using(var context = new Context()) { - protected override void Seed(Context context) - { - context.Customers.Add(new Customer - { - Id = 1, - FirstName = "Bob", - LastName = "Smith", - }); - - base.Seed(context); - } + var model = ProjectTo(context.Customers).Single(); + model.Id.ShouldBe(1); + model.FirstName.ShouldBe("Bob"); + model.LastName.ShouldBe("Smith"); } + } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection(); - }); + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); - [Fact] - public void Can_map_with_projection() - { - using(var context = new Context()) - { - var model = ProjectTo(context.Customers).Single(); - model.Id.ShouldBe(1); - model.FirstName.ShouldBe("Bob"); - model.LastName.ShouldBe("Smith"); - } - } + await initializer.Migrate(); } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/BuiltInTypes/ProjectEnumerableOfIntToList.cs b/src/IntegrationTests/BuiltInTypes/ProjectEnumerableOfIntToList.cs index c1c273a453..0bbe59fef9 100644 --- a/src/IntegrationTests/BuiltInTypes/ProjectEnumerableOfIntToList.cs +++ b/src/IntegrationTests/BuiltInTypes/ProjectEnumerableOfIntToList.cs @@ -1,77 +1,79 @@ -using System.ComponentModel.DataAnnotations; -using System.Data.Entity; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Linq; +using System.Threading.Tasks; +using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; using Shouldly; using Xunit; -namespace AutoMapper.IntegrationTests +namespace AutoMapper.IntegrationTests.BuiltInTypes; + +public class ProjectEnumerableOfIntToList : AutoMapperSpecBase, IAsyncLifetime { - using UnitTests; - using QueryableExtensions; - using System.Collections.Generic; + public class Customer + { + [Key] + public int Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + public List Items { get; set; } + } - public class ProjectEnumerableOfIntToList : AutoMapperSpecBase + public class Item { - public class Customer - { - [Key] - public int Id { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - public List Items { get; set; } - } + public int Id { get; set; } + } - public class Item - { - public int Id { get; set; } - } + public class CustomerViewModel + { + public string FirstName { get; set; } + public string LastName { get; set; } + public List ItemsIds { get; set; } + } - public class CustomerViewModel - { - public string FirstName { get; set; } - public string LastName { get; set; } - public List ItemsIds { get; set; } - } + public class Context : LocalDbContext + { + public DbSet Customers { get; set; } + public DbSet Items { get; set; } + } - public class Context : DbContext + public class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(Context context) { - public Context() + context.Customers.Add(new Customer { - Database.SetInitializer(new DatabaseInitializer()); - } + FirstName = "Bob", + LastName = "Smith", + Items = new List(new[] { new Item(), new Item(), new Item()}) + }); - public DbSet Customers { get; set; } + base.Seed(context); } + } - public class DatabaseInitializer : DropCreateDatabaseAlways - { - protected override void Seed(Context context) - { - context.Customers.Add(new Customer - { - Id = 1, - FirstName = "Bob", - LastName = "Smith", - Items = new List(new[] { new Item { Id = 1 }, new Item { Id = 3 }, new Item { Id = 3 } }) - }); + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection().ForMember(d=>d.ItemsIds, o=>o.MapFrom(s=>s.Items.Select(i=>i.Id))); + }); - base.Seed(context); - } + [Fact] + public void Can_map_with_projection() + { + using(var context = new Context()) + { + var customer = ProjectTo(context.Customers).Single(); + customer.ItemsIds.SequenceEqual(new int[] { 1, 2, 3 }).ShouldBeTrue(); } + } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection().ForMember(d=>d.ItemsIds, o=>o.MapFrom(s=>s.Items.Select(i=>i.Id))); - }); + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); - [Fact] - public void Can_map_with_projection() - { - using(var context = new Context()) - { - var customer = ProjectTo(context.Customers).Single(); - customer.ItemsIds.SequenceEqual(new int[] { 1, 2, 3 }).ShouldBeTrue(); - } - } + await initializer.Migrate(); } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/BuiltInTypes/ProjectUsing.cs b/src/IntegrationTests/BuiltInTypes/ProjectUsing.cs index 8cd1e09bcd..4c19e6a3c8 100644 --- a/src/IntegrationTests/BuiltInTypes/ProjectUsing.cs +++ b/src/IntegrationTests/BuiltInTypes/ProjectUsing.cs @@ -1,141 +1,148 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.Data.Entity; using System.Linq; -using Xunit; +using System.Threading.Tasks; +using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; using Shouldly; +using Xunit; -namespace AutoMapper.IntegrationTests.Net4 -{ - using UnitTests; - using QueryableExtensions; +namespace AutoMapper.IntegrationTests.BuiltInTypes; - public class ProjectUsingWithNullables : AutoMapperSpecBase +public class ProjectUsingWithNullables : AutoMapperSpecBase, IAsyncLifetime +{ + public class MyProfile : Profile { - public class MyProfile : Profile + public MyProfile() { - public MyProfile() - { - CreateProjection(); - CreateProjection().ConvertUsing(x => (MyEnum)x); - CreateProjection().ConvertUsing(x => x.HasValue ? (MyEnum)x.Value : MyEnum.Value1); - } + CreateProjection(); + CreateProjection().ConvertUsing(x => (MyEnum)x); + CreateProjection().ConvertUsing(x => x.HasValue ? (MyEnum)x.Value : MyEnum.Value1); } + } - public enum MyEnum - { - Value1 = 0, - Value2 = 1 - } + public enum MyEnum + { + Value1 = 0, + Value2 = 1 + } - public class MyTable - { - public int Id { get; set; } - public int EnumValue { get; set; } - public int? EnumValueNullable { get; set; } - } + public class MyTable + { + public int Id { get; set; } + public int EnumValue { get; set; } + public int? EnumValueNullable { get; set; } + } - public class MyTableModel - { - public int Id { get; set; } - public MyEnum EnumValue { get; set; } - public MyEnum EnumValueNullable { get; set; } - } + public class MyTableModel + { + public int Id { get; set; } + public MyEnum EnumValue { get; set; } + public MyEnum EnumValueNullable { get; set; } + } - public class DatabaseInitializer : CreateDatabaseIfNotExists + public class DatabaseInitializer : CreateDatabaseIfNotExists + { + protected override void Seed(TestContext context) { - protected override void Seed(TestContext context) - { - context.MyTable.AddRange(new[]{ - new MyTable { Id = 1, EnumValue = (int)MyEnum.Value2 }, - new MyTable { Id = 2, EnumValueNullable = (int?)MyEnum.Value1 }, - }); - base.Seed(context); - } + context.MyTable.AddRange(new[]{ + new MyTable { EnumValue = (int)MyEnum.Value2 }, + new MyTable { EnumValueNullable = (int?)MyEnum.Value1 }, + }); + base.Seed(context); } + } - public class TestContext : DbContext - { - public TestContext() - { - Database.SetInitializer(new DatabaseInitializer()); - } - public DbSet MyTable { get; set; } - } - protected override MapperConfiguration CreateConfiguration() => new(cfg => cfg.AddProfile()); + public class TestContext : LocalDbContext + { + public DbSet MyTable { get; set; } + } + protected override MapperConfiguration CreateConfiguration() => new(cfg => cfg.AddProfile()); - [Fact] - public void Should_project_ok() + [Fact] + public void Should_project_ok() + { + using(var context = new TestContext()) { - using(var context = new TestContext()) - { - var results = ProjectTo(context.MyTable).ToList(); - results[0].Id.ShouldBe(1); - results[0].EnumValue.ShouldBe(MyEnum.Value2); - results[0].EnumValueNullable.ShouldBe(MyEnum.Value1); - results[1].Id.ShouldBe(2); - results[1].EnumValue.ShouldBe(MyEnum.Value1); - results[1].EnumValueNullable.ShouldBe(MyEnum.Value1); - } + var results = ProjectTo(context.MyTable).ToList(); + results[0].Id.ShouldBe(1); + results[0].EnumValue.ShouldBe(MyEnum.Value2); + results[0].EnumValueNullable.ShouldBe(MyEnum.Value1); + results[1].Id.ShouldBe(2); + results[1].EnumValue.ShouldBe(MyEnum.Value1); + results[1].EnumValueNullable.ShouldBe(MyEnum.Value1); } } - public class ProjectUsingBug : AutoMapperSpecBase + public async Task InitializeAsync() { - public class Parent - { - [Key] - public int ID { get; set; } - public string ParentTitle { get; set; } + var initializer = new DatabaseInitializer(); - public ICollection Children { get; set; } - } + await initializer.Migrate(); + } - public class Children - { - public int ID { get; set; } - public string ChildTitle { get; set; } - } + public Task DisposeAsync() => Task.CompletedTask; +} - public class ParentVM - { - [Key] - public int ID { get; set; } - public string ParentTitle { get; set; } - public List Children { get; set; } - } +public class ProjectUsingBug : AutoMapperSpecBase, IAsyncLifetime +{ + public class Parent + { + [Key] + public int ID { get; set; } + public string ParentTitle { get; set; } + + public ICollection Children { get; set; } + } + + public class Children + { + public int ID { get; set; } + public string ChildTitle { get; set; } + } + + public class ParentVM + { + [Key] + public int ID { get; set; } + public string ParentTitle { get; set; } + public List Children { get; set; } + } - public partial class ApplicationDBContext : DbContext + public partial class ApplicationDBContext : LocalDbContext + { + protected override void OnModelCreating(ModelBuilder modelBuilder) { - public ApplicationDBContext() - { - Database.SetInitializer(new CreateDatabaseIfNotExists()); - } - - protected override void OnModelCreating(DbModelBuilder modelBuilder) - { - modelBuilder.Entity() - .HasMany(x => x.Children); - } - - public DbSet Parents { get; set; } - public DbSet Children { get; set; } + modelBuilder.Entity() + .HasMany(x => x.Children); } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection(); - cfg.CreateProjection() - .ConvertUsing(c => c.ID); - }); + public DbSet Parents { get; set; } + public DbSet Children { get; set; } + } + + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection(); + cfg.CreateProjection() + .ConvertUsing(c => c.ID); + }); - [Fact] - public void can_map_with_projection() + [Fact] + public void can_map_with_projection() + { + using (var db = new ApplicationDBContext()) { - using (var db = new ApplicationDBContext()) - { - var result = ProjectTo(db.Parents); - } + var result = ProjectTo(db.Parents); } } + + public async Task InitializeAsync() + { + var initializer = new CreateDatabaseIfNotExists(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/ChildClassTests.cs b/src/IntegrationTests/ChildClassTests.cs index 5c9a9f81bb..3aa6119111 100644 --- a/src/IntegrationTests/ChildClassTests.cs +++ b/src/IntegrationTests/ChildClassTests.cs @@ -1,17 +1,16 @@ -using System.ComponentModel.DataAnnotations; -using System.Data.Entity; +using System; +using System.ComponentModel.DataAnnotations; using System.Linq; -using Xunit; +using System.Threading.Tasks; +using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; using Shouldly; +using Xunit; -namespace AutoMapper.IntegrationTests.Net4 +namespace AutoMapper.IntegrationTests { namespace ChildClassTests { - using AutoMapper.UnitTests; - using QueryableExtensions; - using System; - public class Base { public int BaseID { get; set; } @@ -44,31 +43,24 @@ public class SubDTO public string Sub1 { get; set; } } - public class TestContext : DbContext + public class TestContext : LocalDbContext { - public TestContext() - : base() - { - Database.SetInitializer(new DatabaseInitializer()); - } - public DbSet Bases { get; set; } public DbSet Subs { get; set; } - } public class DatabaseInitializer : DropCreateDatabaseAlways { protected override void Seed(TestContext testContext) { - testContext.Bases.Add(new Base() { BaseID = 1, Base1 = "base1", Sub = new Sub() { BaseId = 1, Sub1 = "sub1" } }); + testContext.Bases.Add(new Base() { Base1 = "base1", Sub = new Sub() { Sub1 = "sub1" } }); base.Seed(testContext); } } - public class UnitTest : AutoMapperSpecBase + public class UnitTest : AutoMapperSpecBase, IAsyncLifetime { protected override MapperConfiguration CreateConfiguration() => new(cfg => { @@ -81,7 +73,7 @@ public void AutoMapperEFRelationsTest() { using (var context = new TestContext()) { - var baseEntitiy = context.Bases.FirstOrDefault(); + var baseEntitiy = context.Bases.Include(b => b.Sub).FirstOrDefault(); baseEntitiy.ShouldNotBeNull(); baseEntitiy.BaseID.ShouldBe(1); baseEntitiy.Sub.Sub1.ShouldBe("sub1"); @@ -111,6 +103,15 @@ public void AutoMapperEFRelationsTest() } [Fact] public void MapShouldThrow() => new Action(() => Mapper.Map(new Sub())).ShouldThrow().Message.ShouldBe("CreateProjection works with ProjectTo, not with Map."); + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } } diff --git a/src/IntegrationTests/CreateDatabaseIfNotExists.cs b/src/IntegrationTests/CreateDatabaseIfNotExists.cs new file mode 100644 index 0000000000..d6ef719cd2 --- /dev/null +++ b/src/IntegrationTests/CreateDatabaseIfNotExists.cs @@ -0,0 +1,30 @@ +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; + +namespace AutoMapper.IntegrationTests; + +public class CreateDatabaseIfNotExists : DropCreateDatabaseAlways + where TContext : DbContext, new() +{ + +} + +public class DropCreateDatabaseAlways where TContext : DbContext, new() +{ + protected virtual void Seed(TContext context) + { + + } + + public async Task Migrate() + { + await using var context = new TContext(); + + await context.Database.EnsureDeletedAsync(); + await context.Database.EnsureCreatedAsync(); + + Seed(context); + + await context.SaveChangesAsync(); + } +} \ No newline at end of file diff --git a/src/IntegrationTests/CustomMapFrom/CustomMapFromTest.cs b/src/IntegrationTests/CustomMapFrom/CustomMapFromTest.cs index 2dc38923f4..dd70b2ca6e 100644 --- a/src/IntegrationTests/CustomMapFrom/CustomMapFromTest.cs +++ b/src/IntegrationTests/CustomMapFrom/CustomMapFromTest.cs @@ -1,18 +1,15 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Data.Entity; +using System.ComponentModel.DataAnnotations; using System.Linq; -using Xunit; +using System.Threading.Tasks; +using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; using Shouldly; +using Xunit; -namespace AutoMapper.IntegrationTests.Net4 +namespace AutoMapper.IntegrationTests.CustomMapFrom { namespace CustomMapFromTest { - using AutoMapper.UnitTests; - using QueryableExtensions; - public class Customer { [Key] @@ -40,14 +37,8 @@ public class CustomerViewModel public string FullAddress { get; set; } } - public class Context : DbContext + public class Context : LocalDbContext { - public Context() - : base() - { - Database.SetInitializer(new DatabaseInitializer()); - } - public DbSet Customers { get; set; } public DbSet
Addresses { get; set; } @@ -59,12 +50,10 @@ protected override void Seed(Context context) { context.Customers.Add(new Customer { - Id = 1, FirstName = "Bob", LastName = "Smith", Address = new Address { - Id = 1, Street = "123 Anywhere", City = "Austin", State = "TX" @@ -75,7 +64,7 @@ protected override void Seed(Context context) } } - public class AutoMapperQueryableExtensionsThrowsNullReferenceExceptionSpec : AutoMapperSpecBase + public class AutoMapperQueryableExtensionsThrowsNullReferenceExceptionSpec : AutoMapperSpecBase, IAsyncLifetime { protected override MapperConfiguration CreateConfiguration() => new(cfg => { @@ -110,6 +99,15 @@ public void can_map_with_projection() }); } } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } } } \ No newline at end of file diff --git a/src/IntegrationTests/CustomMapFrom/MapObjectPropertyFromSubQuery.cs b/src/IntegrationTests/CustomMapFrom/MapObjectPropertyFromSubQuery.cs index 9098d22d9b..2b4d1010bd 100644 --- a/src/IntegrationTests/CustomMapFrom/MapObjectPropertyFromSubQuery.cs +++ b/src/IntegrationTests/CustomMapFrom/MapObjectPropertyFromSubQuery.cs @@ -1,1028 +1,1079 @@ -using Shouldly; -using System.Linq; -using System.Collections.Generic; -using AutoMapper.UnitTests; -using System.Data.Entity; -using Xunit; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; using System.Linq.Expressions; -namespace AutoMapper.IntegrationTests +using System.Threading.Tasks; +using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; +using Shouldly; +using Xunit; + +namespace AutoMapper.IntegrationTests.CustomMapFrom; + +public class MemberWithSubQueryProjections : AutoMapperSpecBase, IAsyncLifetime { - public class MemberWithSubQueryProjections : AutoMapperSpecBase + public class Customer { - public class Customer - { - [Key] - public int Id { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - public ICollection Items { get; set; } - } - public class Item - { - public int Id { get; set; } - public int Code { get; set; } - } - public class ItemModel - { - public int Id { get; set; } - public int Code { get; set; } - } - public class CustomerViewModel - { - public CustomerNameModel Name { get; set; } - public ItemModel FirstItem { get; set; } - } - public class CustomerNameModel - { - public string FirstName { get; set; } - public string LastName { get; set; } - } - public class Context : DbContext - { - public Context() => Database.SetInitializer(new DatabaseInitializer()); - public DbSet Customers { get; set; } - } - public class DatabaseInitializer : DropCreateDatabaseAlways - { - protected override void Seed(Context context) - { - context.Customers.Add(new Customer - { - Id = 1, FirstName = "Bob", LastName = "Smith", Items = new[] { new Item { Code = 1 }, new Item { Code = 3 }, new Item { Code = 5 } } - }); - base.Seed(context); - } - } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection() - .ForMember(dst => dst.Name, opt => opt.MapFrom(src => src.LastName != null ? src : null)) - .ForMember(dst => dst.FirstItem, opt => opt.MapFrom(src => src.Items.FirstOrDefault())); - cfg.CreateProjection(); - cfg.CreateProjection(); - }); - [Fact] - public void Should_work() - { - using (var context = new Context()) - { - var resultQuery = ProjectTo(context.Customers); - var result = resultQuery.Single(); - result.Name.FirstName.ShouldBe("Bob"); - result.Name.LastName.ShouldBe("Smith"); - result.FirstItem.Id.ShouldBe(1); - result.FirstItem.Code.ShouldBe(1); - } - } + [Key] + public int Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + public ICollection Items { get; set; } } - public class MemberWithSubQueryProjectionsNoMap : AutoMapperSpecBase + public class Item { - public class Customer - { - [Key] - public int Id { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - public ICollection Items { get; set; } - } - public class Item - { - public int Id { get; set; } - public int Code { get; set; } - } - public class ItemModel - { - public int Id { get; set; } - public int Code { get; set; } - } - public class CustomerViewModel - { - public string Name { get; set; } - public ItemModel FirstItem { get; set; } - } - public class Context : DbContext - { - public Context() => Database.SetInitializer(new DatabaseInitializer()); - public DbSet Customers { get; set; } - } - public class DatabaseInitializer : DropCreateDatabaseAlways - { - protected override void Seed(Context context) - { - context.Customers.Add(new Customer - { - Id = 1, - FirstName = "Bob", - LastName = "Smith", - Items = new[] { new Item { Code = 1 }, new Item { Code = 3 }, new Item { Code = 5 } } - }); - base.Seed(context); - } - } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection() - .ForMember(dst => dst.Name, opt => opt.MapFrom(src => src.LastName != null ? src.LastName : null)) - .ForMember(dst => dst.FirstItem, opt => opt.MapFrom(src => src.Items.FirstOrDefault())); - cfg.CreateProjection(); - }); - [Fact] - public void Should_work() + public int Id { get; set; } + public int Code { get; set; } + } + public class ItemModel + { + public int Id { get; set; } + public int Code { get; set; } + } + public class CustomerViewModel + { + public CustomerNameModel Name { get; set; } + public ItemModel FirstItem { get; set; } + } + public class CustomerNameModel + { + public string FirstName { get; set; } + public string LastName { get; set; } + } + public class Context : LocalDbContext + { + public DbSet Customers { get; set; } + } + public class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(Context context) { - using (var context = new Context()) + context.Customers.Add(new Customer { - var resultQuery = ProjectTo(context.Customers); - var result = resultQuery.Single(); - result.Name.ShouldBe("Smith"); - result.FirstItem.Id.ShouldBe(1); - result.FirstItem.Code.ShouldBe(1); - } + FirstName = "Bob", + LastName = "Smith", + Items = new[] { new Item { Code = 1 }, new Item { Code = 3 }, new Item { Code = 5 } } + }); + base.Seed(context); } } - public class MapObjectPropertyFromSubQueryTypeNameMax : AutoMapperSpecBase + protected override MapperConfiguration CreateConfiguration() => new(cfg => { - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection() - .ForMember(d => d.Price, o => o.MapFrom(source => source.Articles.Where(x => x.IsDefault && x.NationId == 1 && source.ECommercePublished).FirstOrDefault())); - cfg.CreateProjection() - .ForMember(d => d.RegionId, o => o.MapFrom(s => s.NationId)); - }); - - [Fact] - public void Should_cache_the_subquery() + cfg.CreateProjection() + .ForMember(dst => dst.Name, opt => opt.MapFrom(src => src.LastName != null ? src : null)) + .ForMember(dst => dst.FirstItem, opt => opt.MapFrom(src => src.Items.FirstOrDefault())); + cfg.CreateProjection(); + cfg.CreateProjection(); + }); + [Fact] + public void Should_work() + { + using (var context = new Context()) { - using(var context = new ClientContext()) - { - var projection = ProjectTo(context.Products); - var counter = new FirstOrDefaultCounter(); - counter.Visit(projection.Expression); - counter.Count.ShouldBe(1); - var productModel = projection.First(); - productModel.Price.RegionId.ShouldBe((short)1); - productModel.Price.IsDefault.ShouldBeTrue(); - productModel.Price.Id.ShouldBe(1); - productModel.Id.ShouldBe(1); - } + var resultQuery = ProjectTo(context.Customers); + var result = resultQuery.Single(); + result.Name.FirstName.ShouldBe("Bob"); + result.Name.LastName.ShouldBe("Smith"); + result.FirstItem.Id.ShouldBe(1); + result.FirstItem.Code.ShouldBe(1); } + } - class FirstOrDefaultCounter : ExpressionVisitor - { - public int Count; + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); - protected override Expression VisitMethodCall(MethodCallExpression node) - { - if(node.Method.Name == "FirstOrDefault") - { - Count++; - } - return base.VisitMethodCall(node); - } - } + await initializer.Migrate(); + } - public partial class Article + public Task DisposeAsync() => Task.CompletedTask; +} +public class MemberWithSubQueryProjectionsNoMap : AutoMapperSpecBase, IAsyncLifetime +{ + public class Customer + { + [Key] + public int Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + public ICollection Items { get; set; } + } + public class Item + { + public int Id { get; set; } + public int Code { get; set; } + } + public class ItemModel + { + public int Id { get; set; } + public int Code { get; set; } + } + public class CustomerViewModel + { + public string Name { get; set; } + public ItemModel FirstItem { get; set; } + } + public class Context : LocalDbContext + { + public DbSet Customers { get; set; } + } + public class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(Context context) { - public int Id { get; set; } - public int ProductId { get; set; } - public bool IsDefault { get; set; } - public short NationId { get; set; } - public virtual Product Product { get; set; } + context.Customers.Add(new Customer + { + FirstName = "Bob", + LastName = "Smith", + Items = new[] { new Item { Code = 1 }, new Item { Code = 3 }, new Item { Code = 5 } } + }); + base.Seed(context); } - - public partial class Product + } + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection() + .ForMember(dst => dst.Name, opt => opt.MapFrom(src => src.LastName != null ? src.LastName : null)) + .ForMember(dst => dst.FirstItem, opt => opt.MapFrom(src => src.Items.FirstOrDefault())); + cfg.CreateProjection(); + }); + [Fact] + public void Should_work() + { + using (var context = new Context()) { - public int Id { get; set; } - public string Name { get; set; } - public bool ECommercePublished { get; set; } - public virtual ICollection
Articles { get; set; } - public int Value { get; } - [NotMapped] - public int NotMappedValue { get; set; } - public virtual List
OtherArticles { get; } - public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName1 { get; set; } - public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName2 { get; set; } - public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName3 { get; set; } - public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName4 { get; set; } - public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName5 { get; set; } - public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName6 { get; set; } - public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName7 { get; set; } - public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName8 { get; set; } - public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName9 { get; set; } - public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName10 { get; set; } - public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName11 { get; set; } + var resultQuery = ProjectTo(context.Customers); + var result = resultQuery.Single(); + result.Name.ShouldBe("Smith"); + result.FirstItem.Id.ShouldBe(1); + result.FirstItem.Code.ShouldBe(1); } + } - public class PriceModel - { - public int Id { get; set; } - public short RegionId { get; set; } - public bool IsDefault { get; set; } - } + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); - public class ProductModel - { - public int Id { get; set; } - public PriceModel Price { get; set; } - public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName1 { get; set; } - public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName2 { get; set; } - public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName3 { get; set; } - public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName4 { get; set; } - public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName5 { get; set; } - public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName6 { get; set; } - public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName7 { get; set; } - public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName8 { get; set; } - public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName9 { get; set; } - public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName10 { get; set; } - public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName11 { get; set; } + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; +} +public class MapObjectPropertyFromSubQueryTypeNameMax : AutoMapperSpecBase, IAsyncLifetime +{ + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection() + .ForMember(d => d.Price, o => o.MapFrom(source => source.Articles.Where(x => x.IsDefault && x.NationId == 1 && source.ECommercePublished).FirstOrDefault())); + cfg.CreateProjection() + .ForMember(d => d.RegionId, o => o.MapFrom(s => s.NationId)); + }); + + [Fact] + public void Should_cache_the_subquery() + { + using (var context = new ClientContext()) + { + var projection = ProjectTo(context.Products); + var counter = new FirstOrDefaultCounter(); + counter.Visit(projection.Expression); + counter.Count.ShouldBe(1); + var productModel = projection.First(); + productModel.Price.RegionId.ShouldBe((short)1); + productModel.Price.IsDefault.ShouldBeTrue(); + productModel.Price.Id.ShouldBe(1); + productModel.Id.ShouldBe(1); } + } + + class FirstOrDefaultCounter : ExpressionVisitor + { + public int Count; - class Initializer : DropCreateDatabaseAlways + protected override Expression VisitMethodCall(MethodCallExpression node) { - protected override void Seed(ClientContext context) + if (node.Method.Name == "FirstOrDefault") { - context.Products.Add(new Product { ECommercePublished = true, Articles = new[] { new Article { IsDefault = true, NationId = 1, ProductId = 1 } } }); + Count++; } + return base.VisitMethodCall(node); } + } - class ClientContext : DbContext - { - protected override void OnModelCreating(DbModelBuilder modelBuilder) - { - Database.SetInitializer(new Initializer()); - } + public partial class Article + { + public int Id { get; set; } + public int ProductId { get; set; } + public bool IsDefault { get; set; } + public short NationId { get; set; } + public virtual Product Product { get; set; } + } - public DbSet Products { get; set; } - } + public partial class Product + { + public int Id { get; set; } + public string Name { get; set; } + public bool ECommercePublished { get; set; } + public virtual ICollection
Articles { get; set; } + public int Value { get; } + [NotMapped] + public int NotMappedValue { get; set; } + public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName1 { get; set; } + public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName2 { get; set; } + public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName3 { get; set; } + public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName4 { get; set; } + public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName5 { get; set; } + public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName6 { get; set; } + public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName7 { get; set; } + public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName8 { get; set; } + public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName9 { get; set; } + public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName10 { get; set; } + public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName11 { get; set; } } - public class MapObjectPropertyFromSubQueryExplicitExpansion : AutoMapperSpecBase + public class PriceModel { - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection() - .ForMember(d => d.Price, o => - { - o.MapFrom(source => source.Articles.Where(x => x.IsDefault && x.NationId == 1 && source.ECommercePublished).FirstOrDefault()); - o.ExplicitExpansion(); - }); - cfg.CreateProjection() - .ForMember(d => d.RegionId, o => o.MapFrom(s => s.NationId)); - }); - - [Fact] - public void Should_map_ok() + public int Id { get; set; } + public short RegionId { get; set; } + public bool IsDefault { get; set; } + } + + public class ProductModel + { + public int Id { get; set; } + public PriceModel Price { get; set; } + public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName1 { get; set; } + public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName2 { get; set; } + public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName3 { get; set; } + public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName4 { get; set; } + public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName5 { get; set; } + public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName6 { get; set; } + public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName7 { get; set; } + public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName8 { get; set; } + public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName9 { get; set; } + public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName10 { get; set; } + public int VeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnNameVeryLongColumnName11 { get; set; } + } + + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(ClientContext context) { - using(var context = new ClientContext()) - { - var projection = ProjectTo(context.Products); - var counter = new FirstOrDefaultCounter(); - counter.Visit(projection.Expression); - counter.Count.ShouldBe(0); - var productModel = projection.First(); - productModel.Price.ShouldBeNull(); - productModel.Id.ShouldBe(1); - } + context.Products.Add(new Product { ECommercePublished = true, Articles = new[] { new Article { IsDefault = true, NationId = 1, ProductId = 1 } } }); } + } - class FirstOrDefaultCounter : ExpressionVisitor - { - public int Count; + class ClientContext : LocalDbContext + { + public DbSet Products { get; set; } + } - protected override Expression VisitMethodCall(MethodCallExpression node) - { - if(node.Method.Name == "FirstOrDefault") - { - Count++; - } - return base.VisitMethodCall(node); - } - } + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); - public partial class Article - { - public int Id { get; set; } - public int ProductId { get; set; } - public bool IsDefault { get; set; } - public short NationId { get; set; } - public virtual Product Product { get; set; } - } + await initializer.Migrate(); + } - public partial class Product - { - public int Id { get; set; } - public string Name { get; set; } - public bool ECommercePublished { get; set; } - public virtual ICollection
Articles { get; set; } - public int Value { get; } - public virtual List
OtherArticles { get; } - } + public Task DisposeAsync() => Task.CompletedTask; +} - public class PriceModel +public class MapObjectPropertyFromSubQueryExplicitExpansion : AutoMapperSpecBase, IAsyncLifetime +{ + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection() + .ForMember(d => d.Price, o => + { + o.MapFrom(source => source.Articles.Where(x => x.IsDefault && x.NationId == 1 && source.ECommercePublished).FirstOrDefault()); + o.ExplicitExpansion(); + }); + cfg.CreateProjection() + .ForMember(d => d.RegionId, o => o.MapFrom(s => s.NationId)); + }); + + [Fact] + public void Should_map_ok() + { + using (var context = new ClientContext()) { - public int Id { get; set; } - public short RegionId { get; set; } - public bool IsDefault { get; set; } + var projection = ProjectTo(context.Products); + var counter = new FirstOrDefaultCounter(); + counter.Visit(projection.Expression); + counter.Count.ShouldBe(0); + var productModel = projection.First(); + productModel.Price.ShouldBeNull(); + productModel.Id.ShouldBe(1); } + } - public class ProductModel - { - public int Id { get; set; } - public PriceModel Price { get; set; } - } + class FirstOrDefaultCounter : ExpressionVisitor + { + public int Count; - class Initializer : DropCreateDatabaseAlways + protected override Expression VisitMethodCall(MethodCallExpression node) { - protected override void Seed(ClientContext context) + if (node.Method.Name == "FirstOrDefault") { - context.Products.Add(new Product { ECommercePublished = true, Articles = new[] { new Article { IsDefault = true, NationId = 1, ProductId = 1 } } }); + Count++; } + return base.VisitMethodCall(node); } + } - class ClientContext : DbContext - { - protected override void OnModelCreating(DbModelBuilder modelBuilder) - { - Database.SetInitializer(new Initializer()); - } + public partial class Article + { + public int Id { get; set; } + public int ProductId { get; set; } + public bool IsDefault { get; set; } + public short NationId { get; set; } + public virtual Product Product { get; set; } + } - public DbSet Products { get; set; } - } + public partial class Product + { + public int Id { get; set; } + public string Name { get; set; } + public bool ECommercePublished { get; set; } + public virtual ICollection
Articles { get; set; } + public int Value { get; } } - public class MapObjectPropertyFromSubQuery : AutoMapperSpecBase + public class PriceModel { - protected override MapperConfiguration CreateConfiguration() => new(cfg=> - { - cfg.CreateProjection() - .ForMember(d => d.Price, o => o.MapFrom(source => source.Articles.Where(x => x.IsDefault && x.NationId == 1 && source.ECommercePublished).FirstOrDefault())); - cfg.CreateProjection() - .ForMember(d => d.RegionId, o => o.MapFrom(s => s.NationId)); - }); - - [Fact] - public void Should_cache_the_subquery() + public int Id { get; set; } + public short RegionId { get; set; } + public bool IsDefault { get; set; } + } + + public class ProductModel + { + public int Id { get; set; } + public PriceModel Price { get; set; } + } + + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(ClientContext context) { - using(var context = new ClientContext()) - { - var projection = ProjectTo(context.Products); - var counter = new FirstOrDefaultCounter(); - counter.Visit(projection.Expression); - counter.Count.ShouldBe(1); - var productModel = projection.First(); - productModel.Price.RegionId.ShouldBe((short)1); - productModel.Price.IsDefault.ShouldBeTrue(); - productModel.Price.Id.ShouldBe(1); - productModel.Id.ShouldBe(1); - } + context.Products.Add(new Product { ECommercePublished = true, Articles = new[] { new Article { IsDefault = true, NationId = 1, ProductId = 1 } } }); } + } - class FirstOrDefaultCounter : ExpressionVisitor - { - public int Count; + class ClientContext : LocalDbContext + { + public DbSet Products { get; set; } + public DbSet
Articles { get; set; } + } - protected override Expression VisitMethodCall(MethodCallExpression node) - { - if(node.Method.Name == "FirstOrDefault") - { - Count++; - } - return base.VisitMethodCall(node); - } - } + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); - public partial class Article - { - public int Id { get; set; } - public int ProductId { get; set; } - public bool IsDefault { get; set; } - public short NationId { get; set; } - public virtual Product Product { get; set; } - } + await initializer.Migrate(); + } - public partial class Product - { - public int Id { get; set; } - public string Name { get; set; } - public bool ECommercePublished { get; set; } - public virtual ICollection
Articles { get; set; } - public int Value { get; } - [NotMapped] - public int NotMappedValue { get; set; } - public virtual List
OtherArticles { get; } - } + public Task DisposeAsync() => Task.CompletedTask; +} - public class PriceModel - { - public int Id { get; set; } - public short RegionId { get; set; } - public bool IsDefault { get; set; } +public class MapObjectPropertyFromSubQuery : AutoMapperSpecBase, IAsyncLifetime +{ + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection() + .ForMember(d => d.Price, o => o.MapFrom(source => source.Articles.Where(x => x.IsDefault && x.NationId == 1 && source.ECommercePublished).FirstOrDefault())); + cfg.CreateProjection() + .ForMember(d => d.RegionId, o => o.MapFrom(s => s.NationId)); + }); + + [Fact] + public void Should_cache_the_subquery() + { + using (var context = new ClientContext()) + { + var projection = ProjectTo(context.Products); + var counter = new FirstOrDefaultCounter(); + counter.Visit(projection.Expression); + counter.Count.ShouldBe(1); + var productModel = projection.First(); + productModel.Price.RegionId.ShouldBe((short)1); + productModel.Price.IsDefault.ShouldBeTrue(); + productModel.Price.Id.ShouldBe(1); + productModel.Id.ShouldBe(1); } + } - public class ProductModel - { - public int Id { get; set; } - public PriceModel Price { get; set; } - } + class FirstOrDefaultCounter : ExpressionVisitor + { + public int Count; - class Initializer : DropCreateDatabaseAlways + protected override Expression VisitMethodCall(MethodCallExpression node) { - protected override void Seed(ClientContext context) + if (node.Method.Name == "FirstOrDefault") { - context.Products.Add(new Product { ECommercePublished = true, Articles = new[] { new Article { IsDefault = true, NationId = 1, ProductId = 1 } } }); + Count++; } + return base.VisitMethodCall(node); } + } - class ClientContext : DbContext - { - protected override void OnModelCreating(DbModelBuilder modelBuilder) - { - Database.SetInitializer(new Initializer()); - } + public partial class Article + { + public int Id { get; set; } + public int ProductId { get; set; } + public bool IsDefault { get; set; } + public short NationId { get; set; } + public virtual Product Product { get; set; } + } - public DbSet Products { get; set; } - } + public partial class Product + { + public int Id { get; set; } + public string Name { get; set; } + public bool ECommercePublished { get; set; } + public virtual ICollection
Articles { get; set; } + public int Value { get; } + [NotMapped] + public int NotMappedValue { get; set; } } - public class MapObjectPropertyFromSubQueryWithInnerObject : AutoMapperSpecBase + public class PriceModel { - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection(); - cfg.CreateProjection() - .ForMember(d => d.Price, o => o.MapFrom(source => source.Articles.Where(x => x.IsDefault && x.NationId == 1 && source.ECommercePublished).FirstOrDefault())); - cfg.CreateProjection() - .ForMember(d => d.RegionId, o => o.MapFrom(s => s.NationId)); - }); - - [Fact] - public void Should_cache_the_subquery() - { - using(var context = new ClientContext()) - { - var projection = ProjectTo(context.ProductArticles); - var counter = new FirstOrDefaultCounter(); - counter.Visit(projection.Expression); - counter.Count.ShouldBe(2); - var productArticleModel = projection.First(); - var productModel = productArticleModel.Product; - productModel.Price.RegionId.ShouldBe((short)1); - productModel.Price.IsDefault.ShouldBeTrue(); - productModel.Price.Id.ShouldBe(1); - productModel.Id.ShouldBe(1); - var otherProductModel = productArticleModel.OtherProduct; - otherProductModel.Price.RegionId.ShouldBe((short)1); - otherProductModel.Price.IsDefault.ShouldBeTrue(); - otherProductModel.Price.Id.ShouldBe(2); - otherProductModel.Id.ShouldBe(2); - } - } + public int Id { get; set; } + public short RegionId { get; set; } + public bool IsDefault { get; set; } + } - public class ProductArticle - { - public int Id { get; set; } - public Product Product { get; set; } - public Product OtherProduct { get; set; } - } + public class ProductModel + { + public int Id { get; set; } + public PriceModel Price { get; set; } + } - public class ProductArticleModel + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(ClientContext context) { - public int Id { get; set; } - public ProductModel Product { get; set; } - public ProductModel OtherProduct { get; set; } + context.Products.Add(new Product { ECommercePublished = true, Articles = new[] { new Article { IsDefault = true, NationId = 1, ProductId = 1 } } }); } + } - public partial class Article - { - public int Id { get; set; } - public int ProductId { get; set; } - public bool IsDefault { get; set; } - public short NationId { get; set; } - public virtual Product Product { get; set; } - } + class ClientContext : LocalDbContext + { + public DbSet Products { get; set; } + } - public partial class Product - { - public int Id { get; set; } - public string Name { get; set; } - public bool ECommercePublished { get; set; } - public virtual ICollection
Articles { get; set; } - } + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); - public class PriceModel - { - public int Id { get; set; } - public short RegionId { get; set; } - public bool IsDefault { get; set; } - } + await initializer.Migrate(); + } - public class ProductModel - { - public int Id { get; set; } - public PriceModel Price { get; set; } - } + public Task DisposeAsync() => Task.CompletedTask; +} - class Initializer : DropCreateDatabaseAlways - { - protected override void Seed(ClientContext context) - { - var product1 = context.Products.Add(new Product { ECommercePublished = true, Articles = new[] { new Article { IsDefault = true, NationId = 1, ProductId = 1 } } }); - var product2 = context.Products.Add(new Product { ECommercePublished = true, Articles = new[] { new Article { IsDefault = true, NationId = 1, ProductId = 2 } } }); - context.ProductArticles.Add(new ProductArticle { Product = product1, OtherProduct = product2 }); - } +public class MapObjectPropertyFromSubQueryWithInnerObject : AutoMapperSpecBase, IAsyncLifetime +{ + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection(); + cfg.CreateProjection() + .ForMember(d => d.Price, o => o.MapFrom(source => source.Articles.Where(x => x.IsDefault && x.NationId == 1 && source.ECommercePublished).FirstOrDefault())); + cfg.CreateProjection() + .ForMember(d => d.RegionId, o => o.MapFrom(s => s.NationId)); + }); + + [Fact] + public void Should_cache_the_subquery() + { + using (var context = new ClientContext()) + { + var projection = ProjectTo(context.ProductArticles); + var counter = new FirstOrDefaultCounter(); + counter.Visit(projection.Expression); + counter.Count.ShouldBe(2); + var productArticleModel = projection.First(); + var productModel = productArticleModel.Product; + productModel.Price.RegionId.ShouldBe((short)1); + productModel.Price.IsDefault.ShouldBeTrue(); + productModel.Price.Id.ShouldBe(1); + productModel.Id.ShouldBe(1); + var otherProductModel = productArticleModel.OtherProduct; + otherProductModel.Price.RegionId.ShouldBe((short)1); + otherProductModel.Price.IsDefault.ShouldBeTrue(); + otherProductModel.Price.Id.ShouldBe(2); + otherProductModel.Id.ShouldBe(2); } + } - class ClientContext : DbContext - { - protected override void OnModelCreating(DbModelBuilder modelBuilder) - { - Database.SetInitializer(new Initializer()); - } + public class ProductArticle + { + public int Id { get; set; } + public Product Product { get; set; } + public Product OtherProduct { get; set; } + } - public DbSet Products { get; set; } - public DbSet ProductArticles { get; set; } - } + public class ProductArticleModel + { + public int Id { get; set; } + public ProductModel Product { get; set; } + public ProductModel OtherProduct { get; set; } } - public class MapObjectPropertyFromSubQueryWithCollection : AutoMapperSpecBase + public partial class Article { - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection(); - cfg.CreateProjection() - .ForMember(d => d.Price, o => o.MapFrom(source => source.Articles.Where(x => x.IsDefault && x.NationId == 1 && source.ECommercePublished).FirstOrDefault())); - cfg.CreateProjection() - .ForMember(d => d.RegionId, o => o.MapFrom(s => s.NationId)); - }); - - [Fact] - public void Should_cache_the_subquery() - { - using(var context = new ClientContext()) - { - var projection = ProjectTo(context.ProductArticles); - var counter = new FirstOrDefaultCounter(); - counter.Visit(projection.Expression); - counter.Count.ShouldBe(1); - var productModel = projection.First().Products.First(); - productModel.Price.RegionId.ShouldBe((short)1); - productModel.Price.IsDefault.ShouldBeTrue(); - productModel.Price.Id.ShouldBe(1); - productModel.Id.ShouldBe(1); - } - } + public int Id { get; set; } + public int ProductId { get; set; } + public bool IsDefault { get; set; } + public short NationId { get; set; } + public virtual Product Product { get; set; } + } - class FirstOrDefaultCounter : ExpressionVisitor - { - public int Count; + public partial class Product + { + public int Id { get; set; } + public string Name { get; set; } + public bool ECommercePublished { get; set; } + public virtual ICollection
Articles { get; set; } + } - protected override Expression VisitMethodCall(MethodCallExpression node) - { - if(node.Method.Name == "FirstOrDefault") - { - Count++; - } - return base.VisitMethodCall(node); - } - } + public class PriceModel + { + public int Id { get; set; } + public short RegionId { get; set; } + public bool IsDefault { get; set; } + } - public class ProductArticle - { - public int Id { get; set; } - public ICollection Products { get; set; } - } + public class ProductModel + { + public int Id { get; set; } + public PriceModel Price { get; set; } + } - public class ProductArticleModel + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(ClientContext context) { - public int Id { get; set; } - public ICollection Products { get; set; } + var product1 = context.Products.Add(new Product { ECommercePublished = true, Articles = new[] { new Article { IsDefault = true, NationId = 1, ProductId = 1 } } }); + var product2 = context.Products.Add(new Product { ECommercePublished = true, Articles = new[] { new Article { IsDefault = true, NationId = 1, ProductId = 2 } } }); + context.ProductArticles.Add(new ProductArticle { Product = product1.Entity, OtherProduct = product2.Entity }); } + } - public partial class Article - { - public int Id { get; set; } - public int ProductId { get; set; } - public bool IsDefault { get; set; } - public short NationId { get; set; } - public virtual Product Product { get; set; } - } + class ClientContext : LocalDbContext + { + public DbSet Products { get; set; } + public DbSet ProductArticles { get; set; } + } - public partial class Product - { - public int Id { get; set; } - public string Name { get; set; } - public bool ECommercePublished { get; set; } - public virtual ICollection
Articles { get; set; } - } + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); - public class PriceModel - { - public int Id { get; set; } - public short RegionId { get; set; } - public bool IsDefault { get; set; } - } + await initializer.Migrate(); + } - public class ProductModel - { - public int Id { get; set; } - public PriceModel Price { get; set; } + public Task DisposeAsync() => Task.CompletedTask; +} + +public class MapObjectPropertyFromSubQueryWithCollection : AutoMapperSpecBase, IAsyncLifetime +{ + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection(); + cfg.CreateProjection() + .ForMember(d => d.Price, o => o.MapFrom(source => source.Articles.Where(x => x.IsDefault && x.NationId == 1 && source.ECommercePublished).FirstOrDefault())); + cfg.CreateProjection() + .ForMember(d => d.RegionId, o => o.MapFrom(s => s.NationId)); + }); + + [Fact] + public void Should_cache_the_subquery() + { + using (var context = new ClientContext()) + { + var projection = ProjectTo(context.ProductArticles); + var counter = new FirstOrDefaultCounter(); + counter.Visit(projection.Expression); + counter.Count.ShouldBe(1); + var productModel = projection.First().Products.First(); + productModel.Price.RegionId.ShouldBe((short)1); + productModel.Price.IsDefault.ShouldBeTrue(); + productModel.Price.Id.ShouldBe(1); + productModel.Id.ShouldBe(1); } + } + + class FirstOrDefaultCounter : ExpressionVisitor + { + public int Count; - class Initializer : DropCreateDatabaseAlways + protected override Expression VisitMethodCall(MethodCallExpression node) { - protected override void Seed(ClientContext context) + if (node.Method.Name == "FirstOrDefault") { - var product = context.Products.Add(new Product { ECommercePublished = true, Articles = new[] { new Article { IsDefault = true, NationId = 1, ProductId = 1 } } }); - context.ProductArticles.Add(new ProductArticle { Products = new[] { product } }); + Count++; } + return base.VisitMethodCall(node); } + } - class ClientContext : DbContext - { - protected override void OnModelCreating(DbModelBuilder modelBuilder) - { - Database.SetInitializer(new Initializer()); - } + public class ProductArticle + { + public int Id { get; set; } + public ICollection Products { get; set; } + } - public DbSet Products { get; set; } - public DbSet ProductArticles { get; set; } - } + public class ProductArticleModel + { + public int Id { get; set; } + public ICollection Products { get; set; } } - public class MapObjectPropertyFromSubQueryWithCollectionSameName : NonValidatingSpecBase + public partial class Article { - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection(); - cfg.CreateProjection() - .ForMember(d=>d.ArticlesModel, o=>o.MapFrom(s=>s)) - .ForMember(d => d.Articles, o => o.MapFrom(source => source.Articles.Where(x => x.IsDefault && x.NationId == 1 && source.ECommercePublished).FirstOrDefault())); - cfg.CreateProjection(); - cfg.CreateProjection() - .ForMember(d => d.RegionId, o => o.MapFrom(s => s.NationId)); - }); - - [Fact] - public void Should_cache_the_subquery() - { - using(var context = new ClientContext()) - { - var projection = ProjectTo(context.ProductArticles); - var counter = new FirstOrDefaultCounter(); - counter.Visit(projection.Expression); - counter.Count.ShouldBe(1); - var productModel = projection.First().Products.First(); - Check(productModel.Articles); - productModel.Id.ShouldBe(1); - productModel.ArticlesCount.ShouldBe(1); - productModel.ArticlesModel.Articles.Count.ShouldBe(1); - Check(productModel.ArticlesModel.Articles.Single()); - } - } + public int Id { get; set; } + public int ProductId { get; set; } + public bool IsDefault { get; set; } + public short NationId { get; set; } + public virtual Product Product { get; set; } + } - private static void Check(PriceModel priceModel) - { - priceModel.RegionId.ShouldBe((short)1); - priceModel.IsDefault.ShouldBeTrue(); - priceModel.Id.ShouldBe(1); - } + public partial class Product + { + public int Id { get; set; } + public string Name { get; set; } + public bool ECommercePublished { get; set; } + public virtual ICollection
Articles { get; set; } + } - class FirstOrDefaultCounter : ExpressionVisitor - { - public int Count; + public class PriceModel + { + public int Id { get; set; } + public short RegionId { get; set; } + public bool IsDefault { get; set; } + } - protected override Expression VisitMethodCall(MethodCallExpression node) - { - if(node.Method.Name == "FirstOrDefault") - { - Count++; - } - return base.VisitMethodCall(node); - } - } + public class ProductModel + { + public int Id { get; set; } + public PriceModel Price { get; set; } + } - public class ProductArticle + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(ClientContext context) { - public int Id { get; set; } - public ICollection Products { get; set; } + var product = context.Products.Add(new Product { ECommercePublished = true, Articles = new[] { new Article { IsDefault = true, NationId = 1, ProductId = 1 } } }); + context.ProductArticles.Add(new ProductArticle { Products = new[] { product.Entity } }); } + } - public class ProductArticleModel - { - public int Id { get; set; } - public ICollection Products { get; set; } - } + class ClientContext : LocalDbContext + { + public DbSet Products { get; set; } + public DbSet ProductArticles { get; set; } + } - public partial class Article - { - public int Id { get; set; } - public int ProductId { get; set; } - public bool IsDefault { get; set; } - public short NationId { get; set; } - public virtual Product Product { get; set; } - } + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); - public partial class Product - { - public int Id { get; set; } - public string Name { get; set; } - public bool ECommercePublished { get; set; } - public virtual ICollection
Articles { get; set; } - } + await initializer.Migrate(); + } - public class PriceModel - { - public int Id { get; set; } - public short RegionId { get; set; } - public bool IsDefault { get; set; } - } + public Task DisposeAsync() => Task.CompletedTask; +} - public class ProductModel - { - public int Id { get; set; } - public PriceModel Articles { get; set; } - public int ArticlesCount { get; set; } - public ArticlesModel ArticlesModel { get; set; } +public class MapObjectPropertyFromSubQueryWithCollectionSameName : NonValidatingSpecBase, IAsyncLifetime +{ + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection(); + cfg.CreateProjection() + .ForMember(d => d.ArticlesModel, o => o.MapFrom(s => s)) + .ForMember(d => d.Articles, o => o.MapFrom(source => source.Articles.Where(x => x.IsDefault && x.NationId == 1 && source.ECommercePublished).FirstOrDefault())); + cfg.CreateProjection(); + cfg.CreateProjection() + .ForMember(d => d.RegionId, o => o.MapFrom(s => s.NationId)); + }); + + [Fact] + public void Should_cache_the_subquery() + { + using (var context = new ClientContext()) + { + var projection = ProjectTo(context.ProductArticles); + var counter = new FirstOrDefaultCounter(); + counter.Visit(projection.Expression); + counter.Count.ShouldBe(1); + var productModel = projection.First().Products.First(); + Check(productModel.Articles); + productModel.Id.ShouldBe(1); + productModel.ArticlesCount.ShouldBe(1); + productModel.ArticlesModel.Articles.Count.ShouldBe(1); + Check(productModel.ArticlesModel.Articles.Single()); } + } - public class ArticlesModel - { - public ICollection Articles { get; set; } - } + private static void Check(PriceModel priceModel) + { + priceModel.RegionId.ShouldBe((short)1); + priceModel.IsDefault.ShouldBeTrue(); + priceModel.Id.ShouldBe(1); + } - class Initializer : DropCreateDatabaseAlways + class FirstOrDefaultCounter : ExpressionVisitor + { + public int Count; + + protected override Expression VisitMethodCall(MethodCallExpression node) { - protected override void Seed(ClientContext context) + if (node.Method.Name == "FirstOrDefault") { - var product = context.Products.Add(new Product { ECommercePublished = true, Articles = new[] { new Article { IsDefault = true, NationId = 1, ProductId = 1 } } }); - context.ProductArticles.Add(new ProductArticle { Products = new[] { product } }); + Count++; } + return base.VisitMethodCall(node); } + } - class ClientContext : DbContext - { - protected override void OnModelCreating(DbModelBuilder modelBuilder) - { - Database.SetInitializer(new Initializer()); - } + public class ProductArticle + { + public int Id { get; set; } + public ICollection Products { get; set; } + } - public DbSet Products { get; set; } - public DbSet ProductArticles { get; set; } - } + public class ProductArticleModel + { + public int Id { get; set; } + public ICollection Products { get; set; } } - public class SubQueryWithMapFromNullable : AutoMapperSpecBase + public partial class Article { - // Source Types - public class Cable - { - public int CableId { get; set; } - public ICollection Ends { get; set; } = new List(); - } + public int Id { get; set; } + public int ProductId { get; set; } + public bool IsDefault { get; set; } + public short NationId { get; set; } + public virtual Product Product { get; set; } + } - public class CableEnd - { - [ForeignKey(nameof(CrossConnectId))] - public virtual Cable CrossConnect { get; set; } - [Column(Order = 0), Key] - public int CrossConnectId { get; set; } - [Column(Order = 1), Key] - public string Name { get; set; } - [ForeignKey(nameof(RackId))] - public virtual Rack Rack { get; set; } - public int? RackId { get; set; } - } + public partial class Product + { + public int Id { get; set; } + public string Name { get; set; } + public bool ECommercePublished { get; set; } + public virtual ICollection
Articles { get; set; } + } - public class DataHall - { - public int DataHallId { get; set; } - public int DataCentreId { get; set; } - public ICollection Racks { get; set; } = new List(); - } + public class PriceModel + { + public int Id { get; set; } + public short RegionId { get; set; } + public bool IsDefault { get; set; } + } - public class Rack - { - public int RackId { get; set; } - [ForeignKey(nameof(DataHallId))] - public virtual DataHall DataHall { get; set; } - public int DataHallId { get; set; } - } + public class ProductModel + { + public int Id { get; set; } + public PriceModel Articles { get; set; } + public int ArticlesCount { get; set; } + public ArticlesModel ArticlesModel { get; set; } + } - // Dest Types - public class CableListModel - { - public int CableId { get; set; } - public CableEndModel AEnd { get; set; } - public CableEndModel AnotherEnd { get; set; } - } + public class ArticlesModel + { + public ICollection Articles { get; set; } + } - public class CableEndModel + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(ClientContext context) { - public string Name { get; set; } - public int? DataHallId { get; set; } + var product = context.Products.Add(new Product { ECommercePublished = true, Articles = new[] { new Article { IsDefault = true, NationId = 1, ProductId = 1 } } }); + context.ProductArticles.Add(new ProductArticle { Products = new[] { product.Entity } }); } + } - class ClientContext : DbContext - { - protected override void OnModelCreating(DbModelBuilder modelBuilder) - { - Database.SetInitializer(new Initializer()); - } + class ClientContext : LocalDbContext + { + public DbSet Products { get; set; } + public DbSet ProductArticles { get; set; } + } + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; +} + +public class SubQueryWithMapFromNullable : AutoMapperSpecBase, IAsyncLifetime +{ + // Source Types + public class Cable + { + public int CableId { get; set; } + public ICollection Ends { get; set; } = new List(); + } + + public class CableEnd + { + [ForeignKey(nameof(CrossConnectId))] + public virtual Cable CrossConnect { get; set; } + [Column(Order = 0), Key] + public int CrossConnectId { get; set; } + [Column(Order = 1), Key] + public string Name { get; set; } + [ForeignKey(nameof(RackId))] + public virtual Rack Rack { get; set; } + public int? RackId { get; set; } + } + + public class DataHall + { + public int DataHallId { get; set; } + public int DataCentreId { get; set; } + public ICollection Racks { get; set; } = new List(); + } + + public class Rack + { + public int RackId { get; set; } + [ForeignKey(nameof(DataHallId))] + public virtual DataHall DataHall { get; set; } + public int DataHallId { get; set; } + } + + // Dest Types + public class CableListModel + { + public int CableId { get; set; } + public CableEndModel AEnd { get; set; } + public CableEndModel AnotherEnd { get; set; } + } - public DbSet Cables { get; set; } - public DbSet CableEnds { get; set; } - public DbSet DataHalls { get; set; } + public class CableEndModel + { + public string Name { get; set; } + public int? DataHallId { get; set; } + } + + class ClientContext : LocalDbContext + { + public DbSet Cables { get; set; } + public DbSet CableEnds { get; set; } + public DbSet DataHalls { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity().HasKey(c => new { c.CrossConnectId, c.Name }); } + } - class Initializer : DropCreateDatabaseAlways + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(ClientContext context) { - protected override void Seed(ClientContext context) + var rack = new Rack(); + var dh = new DataHall { DataCentreId = 10, Racks = { rack } }; + context.DataHalls.Add(dh); + var cable = new Cable { - var rack = new Rack(); - var dh = new DataHall { DataCentreId = 10, Racks = { rack } }; - context.DataHalls.Add(dh); - var cable = new Cable - { - Ends = new List() + Ends = new List() { new CableEnd { Name = "A", Rack = rack}, new CableEnd { Name = "B" }, } - }; - context.Cables.Add(cable); - } + }; + context.Cables.Add(cable); } + } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection().ForMember(dest => dest.DataHallId, opt => opt.MapFrom(src => src.Rack.DataHall.DataCentreId)); - cfg.CreateProjection() - .ForMember(dest => dest.AEnd, opt => opt.MapFrom(src => src.Ends.FirstOrDefault(x => x.Name == "A"))) - .ForMember(dest => dest.AnotherEnd, opt => opt.MapFrom(src => src.Ends.FirstOrDefault(x => x.Name == "B"))); - }); - - [Fact] - public void Should_project_ok() + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection().ForMember(dest => dest.DataHallId, opt => opt.MapFrom(src => src.Rack.DataHall.DataCentreId)); + cfg.CreateProjection() + .ForMember(dest => dest.AEnd, opt => opt.MapFrom(src => src.Ends.FirstOrDefault(x => x.Name == "A"))) + .ForMember(dest => dest.AnotherEnd, opt => opt.MapFrom(src => src.Ends.FirstOrDefault(x => x.Name == "B"))); + }); + + [Fact] + public void Should_project_ok() + { + using (var context = new ClientContext()) { - using(var context = new ClientContext()) - { - var projection = ProjectTo(context.Cables); - var result = projection.Single(); - result.AEnd.DataHallId.ShouldBe(10); - result.AnotherEnd.DataHallId.ShouldBeNull(); - } + var projection = ProjectTo(context.Cables); + var result = projection.Single(); + result.AEnd.DataHallId.ShouldBe(10); + result.AnotherEnd.DataHallId.ShouldBeNull(); } } + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } - public class MapObjectPropertyFromSubQueryCustomSource : AutoMapperSpecBase + public Task DisposeAsync() => Task.CompletedTask; +} + +public class MapObjectPropertyFromSubQueryCustomSource : AutoMapperSpecBase, IAsyncLifetime +{ + protected override MapperConfiguration CreateConfiguration() => new(cfg => { - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection(); - cfg.CreateProjection() - .ForMember(dest => dest.Owner, opt => opt.MapFrom(src => src.Owners.FirstOrDefault())); - cfg.CreateProjection() - .ForMember(dest => dest.Brand, opt => opt.MapFrom(src => src.Product.Brand)); - }); - - public class Owner - { - public int Id { get; set; } - public string Name { get; set; } - } - public class Brand - { - public int Id { get; set; } - public List Owners { get; set; } = new List(); - } - public class Product - { - public int Id { get; set; } - public Brand Brand { get; set; } - } - public class ProductReview - { - public int Id { get; set; } - public Product Product { get; set; } - } - /* Destination types */ - public class ProductReviewDto - { - public int Id { get; set; } - public BrandDto Brand { get; set; } - } - public class BrandDto - { - public int Id { get; set; } - public OwnerDto Owner { get; set; } - } - public class OwnerDto - { - public int Id { get; set; } - public string Name { get; set; } - } + cfg.CreateProjection(); + cfg.CreateProjection() + .ForMember(dest => dest.Owner, opt => opt.MapFrom(src => src.Owners.FirstOrDefault())); + cfg.CreateProjection() + .ForMember(dest => dest.Brand, opt => opt.MapFrom(src => src.Product.Brand)); + }); + + public class Owner + { + public int Id { get; set; } + public string Name { get; set; } + } + public class Brand + { + public int Id { get; set; } + public List Owners { get; set; } = new List(); + } + public class Product + { + public int Id { get; set; } + public Brand Brand { get; set; } + } + public class ProductReview + { + public int Id { get; set; } + public Product Product { get; set; } + } + /* Destination types */ + public class ProductReviewDto + { + public int Id { get; set; } + public BrandDto Brand { get; set; } + } + public class BrandDto + { + public int Id { get; set; } + public OwnerDto Owner { get; set; } + } + public class OwnerDto + { + public int Id { get; set; } + public string Name { get; set; } + } - class ClientContext : DbContext - { - protected override void OnModelCreating(DbModelBuilder modelBuilder) - { - Database.SetInitializer(new Initializer()); - } - public DbSet Owners { get; set; } - public DbSet Products { get; set; } - public DbSet Brands { get; set; } - public DbSet ProductReviews { get; set; } - } + class ClientContext : LocalDbContext + { + public DbSet Owners { get; set; } + public DbSet Products { get; set; } + public DbSet Brands { get; set; } + public DbSet ProductReviews { get; set; } + } - class Initializer : DropCreateDatabaseAlways + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(ClientContext context) { - protected override void Seed(ClientContext context) - { - context.ProductReviews.AddRange(new[]{ - new ProductReview { Product = new Product { Brand = new Brand{ Owners = { new Owner{ Name = "Owner" } } } } }, - new ProductReview { Product = new Product { Brand = new Brand { } } }, - new ProductReview { Product = new Product { } } }); - } + context.ProductReviews.Add(new ProductReview + { Product = new Product { Brand = new Brand { Owners = { new Owner { Name = "Owner" } } } } }); + context.ProductReviews.Add(new ProductReview + { Product = new Product { Brand = new Brand { Owners = { new Owner() } } } }); + context.ProductReviews.Add(new ProductReview { Product = new Product() }); } + } - [Fact] - public void Should_project_ok() + [Fact] + public void Should_project_ok() + { + using (var context = new ClientContext()) { - using(var context = new ClientContext()) - { - var projection = ProjectTo(context.ProductReviews); - var results = projection.ToArray(); - results[0].Brand.Owner.Name.ShouldBe("Owner"); - results[1].Brand.Owner.ShouldBeNull(); - results[2].Brand.ShouldBeNull(); - } + var projection = ProjectTo(context.ProductReviews); + var results = projection.ToArray(); + results.Any(result => result?.Brand?.Owner?.Name == "Owner").ShouldBeTrue(); + results.Any(result => result?.Brand?.Owner == null).ShouldBeTrue(); + results.Any(result => result?.Brand == null).ShouldBeTrue(); } } - public class MemberWithSubQueryIdentity : AutoMapperSpecBase + public async Task InitializeAsync() { - protected override MapperConfiguration CreateConfiguration() => new MapperConfiguration(cfg => - { - cfg.CreateProjection() - .ForMember(dst => dst.DtoSubWrapper, opt => opt.MapFrom(src => src)); - cfg.CreateProjection() - .ForMember(dst => dst.DtoSub, opt => opt.MapFrom(src => src.BEntity.CEntities.FirstOrDefault(x => x.Id == src.CEntityId))); - cfg.CreateProjection(); - }); - [Fact] - public void Should_work() - { - var query = ProjectTo(new ClientContext().AEntities); - var result = query.Single(); - result.DtoSubWrapper.DtoSub.ShouldNotBeNull(); - result.DtoSubWrapper.DtoSub.SubString.ShouldBe("Test"); - } - public class Dto - { - public int Id { get; set; } - public DtoSubWrapper DtoSubWrapper { get; set; } - } - public class DtoSubWrapper - { - public DtoSub DtoSub { get; set; } - } - public class DtoSub - { - public int Id { get; set; } - public string SubString { get; set; } - } - public class AEntity - { - public int Id { get; set; } - public int BEntityId { get; set; } - public int CEntityId { get; set; } - public BEntity BEntity { get; set; } - } - public class BEntity - { - public int Id { get; set; } - public ICollection CEntities { get; set; } - } - public class CEntity - { - public int Id { get; set; } - public int BEntityId { get; set; } - public string SubString { get; set; } - public BEntity BEntity { get; set; } - } - class Initializer : DropCreateDatabaseAlways + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; +} + +public class MemberWithSubQueryIdentity : AutoMapperSpecBase, IAsyncLifetime +{ + protected override MapperConfiguration CreateConfiguration() => new MapperConfiguration(cfg => + { + cfg.CreateProjection() + .ForMember(dst => dst.DtoSubWrapper, opt => opt.MapFrom(src => src)); + cfg.CreateProjection() + .ForMember(dst => dst.DtoSub, opt => opt.MapFrom(src => src.BEntity.CEntities.FirstOrDefault(x => x.Id == src.CEntityId))); + cfg.CreateProjection(); + }); + [Fact] + public void Should_work() + { + var query = ProjectTo(new ClientContext().AEntities); + var result = query.Single(); + result.DtoSubWrapper.DtoSub.ShouldNotBeNull(); + result.DtoSubWrapper.DtoSub.SubString.ShouldBe("Test"); + } + public class Dto + { + public int Id { get; set; } + public DtoSubWrapper DtoSubWrapper { get; set; } + } + public class DtoSubWrapper + { + public DtoSub DtoSub { get; set; } + } + public class DtoSub + { + public int Id { get; set; } + public string SubString { get; set; } + } + public class AEntity + { + public int Id { get; set; } + public int BEntityId { get; set; } + public int CEntityId { get; set; } + public BEntity BEntity { get; set; } + } + public class BEntity + { + public int Id { get; set; } + public ICollection CEntities { get; set; } + } + public class CEntity + { + public int Id { get; set; } + public int BEntityId { get; set; } + public string SubString { get; set; } + public BEntity BEntity { get; set; } + } + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(ClientContext context) { - protected override void Seed(ClientContext context) + context.AEntities.Add(new AEntity { - context.AEntities.Add(new AEntity + CEntityId = 6, + BEntity = new BEntity { - Id = 1, - BEntityId = 1, - CEntityId = 6, - BEntity = new BEntity - { - Id = 1, - CEntities = new List + CEntities = new List { new CEntity { @@ -1031,32 +1082,37 @@ protected override void Seed(ClientContext context) SubString = "Test" } } - }, - }); - } + }, + }); } - class ClientContext : DbContext + } + class ClientContext : LocalDbContext + { + protected override void OnModelCreating(ModelBuilder modelBuilder) { - protected override void OnModelCreating(DbModelBuilder modelBuilder) - { - Database.Log = s => System.Diagnostics.Debug.WriteLine(s); - Database.SetInitializer(new Initializer()); - - modelBuilder.Entity() - .HasRequired(x => x.BEntity) - .WithMany() - .HasForeignKey(x => x.BEntityId); - - modelBuilder.Entity() - .HasMany(x => x.CEntities) - .WithRequired(x => x.BEntity) - .HasForeignKey(x => x.BEntityId); - - modelBuilder.Entity() - .Property(x => x.Id) - .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); - } - public DbSet AEntities { get; set; } + modelBuilder.Entity() + .HasOne(x => x.BEntity) + .WithMany() + .HasForeignKey(x => x.BEntityId); + + modelBuilder.Entity() + .HasMany(x => x.CEntities) + .WithOne(x => x.BEntity) + .HasForeignKey(x => x.BEntityId); + + modelBuilder.Entity() + .Property(x => x.Id) + .ValueGeneratedNever(); } + public DbSet AEntities { get; set; } } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/CustomProjection.cs b/src/IntegrationTests/CustomProjection.cs index ac6de5e64f..094b7694b4 100644 --- a/src/IntegrationTests/CustomProjection.cs +++ b/src/IntegrationTests/CustomProjection.cs @@ -1,167 +1,196 @@ using System.Linq; -using Xunit; +using System.Threading.Tasks; +using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; using Shouldly; -using AutoMapper; -using AutoMapper.QueryableExtensions; -using System.Data.Entity; +using Xunit; + +namespace AutoMapper.IntegrationTests; -namespace AutoMapper.UnitTests.Projection +public class CustomProjectionStringToString : AutoMapperSpecBase, IAsyncLifetime { - public class CustomProjectionStringToString : AutoMapperSpecBase + public class TestContext : LocalDbContext { - public class TestContext : DbContext - { - public TestContext(): base() => Database.SetInitializer(new DatabaseInitializer()); - public DbSet Sources { get; set; } - } - const string _badGreeting = "GRRRRR"; - public class DatabaseInitializer : DropCreateDatabaseAlways - { - protected override void Seed(TestContext testContext) - { - testContext.Sources.Add(new Source { Greeting = _badGreeting }); - base.Seed(testContext); - } - } - protected override MapperConfiguration CreateConfiguration() => new(x => { - x.CreateProjection().ConvertUsing(s => _niceGreeting); - x.CreateProjection(); - x.CreateProjection(); - }); - const string _niceGreeting = "Hello"; - [Fact] - public void Direct_assignability_shouldnt_trump_custom_projection() - { - using (var context = new TestContext()) - { - ProjectTo(context.Sources).Single().Greeting.ShouldBe(_niceGreeting); - } - } - public class Source - { - public int Id { get; set; } - public string Greeting { get; set; } - public int Number { get; set; } - public SourceChild Child { get; set; } - } - public class SourceChild - { - public int Id { get; set; } - public string Greeting { get; set; } - } - class Target - { - public string Greeting { get; set; } - public int? Number { get; set; } - public TargetChild Child { get; set; } - } - class TargetChild - { - public string Greeting { get; set; } - } + public DbSet Sources { get; set; } } - public class CustomProjectionCustomClasses : AutoMapperSpecBase + const string _badGreeting = "GRRRRR"; + public class DatabaseInitializer : DropCreateDatabaseAlways { - public class TestContext : DbContext - { - public TestContext() : base() => Database.SetInitializer(new DatabaseInitializer()); - public DbSet Sources { get; set; } - } - public class DatabaseInitializer : DropCreateDatabaseAlways - { - protected override void Seed(TestContext testContext) - { - testContext.Sources.Add(new Source()); - base.Seed(testContext); - } - } - const string _niceGreeting = "Hello"; - protected override MapperConfiguration CreateConfiguration() => new(x => - { - x.CreateProjection().ConvertUsing(s => new Target { Greeting = _niceGreeting }); - x.CreateProjection(); - }); - [Fact] - public void Should_work() - { - using (var context = new TestContext()) - { - ProjectTo(context.Sources).Single().Greeting.ShouldBe(_niceGreeting); - } - } - public class Source + protected override void Seed(TestContext testContext) { - public int Id { get; set; } - public string Greeting { get; set; } - public int Number { get; set; } - public SourceChild Child { get; set; } - } - public class SourceChild - { - public int Id { get; set; } - public string Greeting { get; set; } - } - class Target - { - public string Greeting { get; set; } - public int? Number { get; set; } - public TargetChild Child { get; set; } - } - class TargetChild - { - public string Greeting { get; set; } + testContext.Sources.Add(new Source { Greeting = _badGreeting }); + base.Seed(testContext); } } - public class CustomProjectionChildClasses : AutoMapperSpecBase + protected override MapperConfiguration CreateConfiguration() => new(x => { + x.CreateProjection().ConvertUsing(s => _niceGreeting); + x.CreateProjection(); + x.CreateProjection(); + }); + const string _niceGreeting = "Hello"; + [Fact] + public void Direct_assignability_shouldnt_trump_custom_projection() { - public class TestContext : DbContext + using (var context = new TestContext()) { - public TestContext() : base() => Database.SetInitializer(new DatabaseInitializer()); - public DbSet Sources { get; set; } + ProjectTo(context.Sources).Single().Greeting.ShouldBe(_niceGreeting); } - public class DatabaseInitializer : DropCreateDatabaseAlways - { - protected override void Seed(TestContext testContext) - { - testContext.Sources.Add(new Source { Child = new SourceChild { } }); - base.Seed(testContext); - } - } - const string _niceGreeting = "Hello"; - protected override MapperConfiguration CreateConfiguration() => new(x => - { - x.CreateProjection(); - x.CreateProjection().ConvertUsing(s => new TargetChild { Greeting = _niceGreeting }); - }); - [Fact] - public void Should_work() - { - using (var context = new TestContext()) - { - ProjectTo(context.Sources).Single().Child.Greeting.ShouldBe(_niceGreeting); - } - } - public class Source + } + public class Source + { + public int Id { get; set; } + public string Greeting { get; set; } + public int Number { get; set; } + public SourceChild Child { get; set; } + } + public class SourceChild + { + public int Id { get; set; } + public string Greeting { get; set; } + } + class Target + { + public string Greeting { get; set; } + public int? Number { get; set; } + public TargetChild Child { get; set; } + } + class TargetChild + { + public string Greeting { get; set; } + } + + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; + +} +public class CustomProjectionCustomClasses : AutoMapperSpecBase, IAsyncLifetime +{ + public class TestContext : LocalDbContext + { + public DbSet Sources { get; set; } + } + public class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(TestContext testContext) { - public int Id { get; set; } - public string Greeting { get; set; } - public int Number { get; set; } - public SourceChild Child { get; set; } + testContext.Sources.Add(new Source()); + base.Seed(testContext); } - public class SourceChild + } + const string _niceGreeting = "Hello"; + protected override MapperConfiguration CreateConfiguration() => new(x => + { + x.CreateProjection().ConvertUsing(s => new Target { Greeting = _niceGreeting }); + x.CreateProjection(); + }); + [Fact] + public void Should_work() + { + using (var context = new TestContext()) { - public int Id { get; set; } - public string Greeting { get; set; } + ProjectTo(context.Sources).Single().Greeting.ShouldBe(_niceGreeting); } - class Target + } + public class Source + { + public int Id { get; set; } + public string Greeting { get; set; } + public int Number { get; set; } + public SourceChild Child { get; set; } + } + public class SourceChild + { + public int Id { get; set; } + public string Greeting { get; set; } + } + class Target + { + public string Greeting { get; set; } + public int? Number { get; set; } + public TargetChild Child { get; set; } + } + class TargetChild + { + public string Greeting { get; set; } + } + + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; + +} +public class CustomProjectionChildClasses : AutoMapperSpecBase, IAsyncLifetime +{ + public class TestContext : LocalDbContext + { + public DbSet Sources { get; set; } + } + public class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(TestContext testContext) { - public string Greeting { get; set; } - public int? Number { get; set; } - public TargetChild Child { get; set; } + testContext.Sources.Add(new Source { Child = new SourceChild { } }); + base.Seed(testContext); } - class TargetChild + } + const string _niceGreeting = "Hello"; + protected override MapperConfiguration CreateConfiguration() => new(x => + { + x.CreateProjection(); + x.CreateProjection().ConvertUsing(s => new TargetChild { Greeting = _niceGreeting }); + }); + [Fact] + public void Should_work() + { + using (var context = new TestContext()) { - public string Greeting { get; set; } + ProjectTo(context.Sources).Single().Child.Greeting.ShouldBe(_niceGreeting); } } + public class Source + { + public int Id { get; set; } + public string Greeting { get; set; } + public int Number { get; set; } + public SourceChild Child { get; set; } + } + public class SourceChild + { + public int Id { get; set; } + public string Greeting { get; set; } + } + class Target + { + public string Greeting { get; set; } + public int? Number { get; set; } + public TargetChild Child { get; set; } + } + class TargetChild + { + public string Greeting { get; set; } + } + + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; + } \ No newline at end of file diff --git a/src/IntegrationTests/ExplicitExpansion/ExpandCollections.cs b/src/IntegrationTests/ExplicitExpansion/ExpandCollections.cs index 0a32ff10fd..08df6fd9ad 100644 --- a/src/IntegrationTests/ExplicitExpansion/ExpandCollections.cs +++ b/src/IntegrationTests/ExplicitExpansion/ExpandCollections.cs @@ -1,115 +1,113 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.Data.Entity; +using System.Diagnostics; using System.Linq; -using AutoMapper.QueryableExtensions; +using System.Threading.Tasks; using AutoMapper.UnitTests; -using Xunit; +using Microsoft.EntityFrameworkCore; using Shouldly; -using System.Diagnostics; +using Xunit; + +namespace AutoMapper.IntegrationTests.ExplicitExpansion; -namespace AutoMapper.IntegrationTests.Net4 +public class ExpandCollections : AutoMapperSpecBase, IAsyncLifetime { - public class ExpandCollections : AutoMapperSpecBase + TrainingCourseDto _course; + + protected override MapperConfiguration CreateConfiguration() => new(cfg => { - TrainingCourseDto _course; + cfg.CreateProjection(); + cfg.CreateProjection(); + cfg.CreateProjection().ForMember(c => c.Category, o => o.ExplicitExpansion()); + }); - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection(); - cfg.CreateProjection(); - cfg.CreateProjection().ForMember(c => c.Category, o => o.ExplicitExpansion()); - }); + [Fact] + public void Should_expand_collections_items() + { + _course.Content[0].Category.CategoryName.ShouldBe("Category 1"); + } - protected override void Because_of() + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(ClientContext context) { - using(var context = new ClientContext()) - { - context.Database.Log = s => Trace.WriteLine(s); - _course = ProjectTo(context.TrainingCourses, null, c => c.Content.Select(co => co.Category)).FirstOrDefault(n => n.CourseName == "Course 1"); - } + var category = new Category { CategoryName = "Category 1" }; + var course = new TrainingCourse { CourseName = "Course 1" }; + context.TrainingCourses.Add(course); + var content = new TrainingContent { ContentName = "Content 1", Category = category }; + context.TrainingContents.Add(content); + course.Content.Add(content); } + } + class ClientContext : LocalDbContext + { + public DbSet Categories { get; set; } + public DbSet TrainingCourses { get; set; } + public DbSet TrainingContents { get; set; } + } - [Fact] - public void Should_expand_collections_items() - { - _course.Content[0].Category.CategoryName.ShouldBe("Category 1"); - } - - class Initializer : DropCreateDatabaseAlways - { - protected override void Seed(ClientContext context) - { - var category = new Category { CategoryName = "Category 1" }; - var course = new TrainingCourse { CourseName = "Course 1" }; - context.TrainingCourses.Add(course); - var content = new TrainingContent { ContentName = "Content 1", Category = category }; - context.TrainingContents.Add(content); - course.Content.Add(content); - } - } + public class TrainingCourse + { + [Key] + public int CourseId { get; set; } - class ClientContext : DbContext - { - public ClientContext() - { - Database.SetInitializer(new Initializer()); - } - public DbSet Categories { get; set; } - public DbSet TrainingCourses { get; set; } - public DbSet TrainingContents { get; set; } - } + public string CourseName { get; set; } - public class TrainingCourse - { - [Key] - public int CourseId { get; set; } + public virtual IList Content { get; set; } = new List(); + } - public string CourseName { get; set; } + public class TrainingContent + { + [Key] + public int ContentId { get; set; } - public virtual IList Content { get; set; } = new List(); - } + public string ContentName { get; set; } - public class TrainingContent - { - [Key] - public int ContentId { get; set; } + public Category Category { get; set; } + } - public string ContentName { get; set; } + public class Category + { + public int CategoryId { get; set; } + public string CategoryName { get; set; } + } - public Category Category { get; set; } - } - public class Category - { - public int CategoryId { get; set; } - public string CategoryName { get; set; } - } + public class TrainingCourseDto + { + public int CourseId { get; set; } + public string CourseName { get; set; } - public class TrainingCourseDto - { - public int CourseId { get; set; } + public virtual IList Content { get; set; } + } - public string CourseName { get; set; } + public class CategoryDto + { + public int CategoryId { get; set; } + public string CategoryName { get; set; } + } - public virtual IList Content { get; set; } - } + public class TrainingContentDto + { + public int ContentId { get; set; } - public class CategoryDto - { - public int CategoryId { get; set; } - public string CategoryName { get; set; } - } + public string ContentName { get; set; } - public class TrainingContentDto - { - public int ContentId { get; set; } + public CategoryDto Category { get; set; } + } + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); - public string ContentName { get; set; } + await initializer.Migrate(); - public CategoryDto Category { get; set; } + using (var context = new ClientContext()) + { + _course = ProjectTo(context.TrainingCourses, null, c => c.Content.Select(co => co.Category)).FirstOrDefault(n => n.CourseName == "Course 1"); } } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/ExplicitExpansion/ExpandCollectionsWithStrings.cs b/src/IntegrationTests/ExplicitExpansion/ExpandCollectionsWithStrings.cs index 9119ac1355..86f802a9e3 100644 --- a/src/IntegrationTests/ExplicitExpansion/ExpandCollectionsWithStrings.cs +++ b/src/IntegrationTests/ExplicitExpansion/ExpandCollectionsWithStrings.cs @@ -1,115 +1,113 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.Data.Entity; +using System.Diagnostics; using System.Linq; -using AutoMapper.QueryableExtensions; +using System.Threading.Tasks; using AutoMapper.UnitTests; -using Xunit; +using Microsoft.EntityFrameworkCore; using Shouldly; -using System.Diagnostics; +using Xunit; + +namespace AutoMapper.IntegrationTests.ExplicitExpansion; -namespace AutoMapper.IntegrationTests.Net4 +public class ExpandCollectionsWithStrings : AutoMapperSpecBase, IAsyncLifetime { - public class ExpandCollectionsWithStrings : AutoMapperSpecBase + TrainingCourseDto _course; + + protected override MapperConfiguration CreateConfiguration() => new(cfg => { - TrainingCourseDto _course; + cfg.CreateProjection(); + cfg.CreateProjection(); + cfg.CreateProjection().ForMember(c => c.Category, o => o.ExplicitExpansion()); + }); - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection(); - cfg.CreateProjection(); - cfg.CreateProjection().ForMember(c => c.Category, o => o.ExplicitExpansion()); - }); + [Fact] + public void Should_expand_collections_items_with_strings() + { + _course.Content[0].Category.CategoryName.ShouldBe("Category 1"); + } - protected override void Because_of() + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(ClientContext context) { - using(var context = new ClientContext()) - { - context.Database.Log = s => Trace.WriteLine(s); - _course = ProjectTo(context.TrainingCourses, null, "Content.Category").FirstOrDefault(n => n.CourseName == "Course 1"); - } + var category = new Category { CategoryName = "Category 1" }; + var course = new TrainingCourse { CourseName = "Course 1" }; + context.TrainingCourses.Add(course); + var content = new TrainingContent { ContentName = "Content 1", Category = category }; + context.TrainingContents.Add(content); + course.Content.Add(content); } + } + class ClientContext : LocalDbContext + { + public DbSet Categories { get; set; } + public DbSet TrainingCourses { get; set; } + public DbSet TrainingContents { get; set; } + } - [Fact] - public void Should_expand_collections_items_with_strings() - { - _course.Content[0].Category.CategoryName.ShouldBe("Category 1"); - } - - class Initializer : DropCreateDatabaseAlways - { - protected override void Seed(ClientContext context) - { - var category = new Category { CategoryName = "Category 1" }; - var course = new TrainingCourse { CourseName = "Course 1" }; - context.TrainingCourses.Add(course); - var content = new TrainingContent { ContentName = "Content 1", Category = category }; - context.TrainingContents.Add(content); - course.Content.Add(content); - } - } + public class TrainingCourse + { + [Key] + public int CourseId { get; set; } - class ClientContext : DbContext - { - public ClientContext() - { - Database.SetInitializer(new Initializer()); - } - public DbSet Categories { get; set; } - public DbSet TrainingCourses { get; set; } - public DbSet TrainingContents { get; set; } - } + public string CourseName { get; set; } - public class TrainingCourse - { - [Key] - public int CourseId { get; set; } + public virtual IList Content { get; set; } = new List(); + } - public string CourseName { get; set; } + public class TrainingContent + { + [Key] + public int ContentId { get; set; } - public virtual IList Content { get; set; } = new List(); - } + public string ContentName { get; set; } - public class TrainingContent - { - [Key] - public int ContentId { get; set; } + public Category Category { get; set; } + } - public string ContentName { get; set; } + public class Category + { + public int CategoryId { get; set; } + public string CategoryName { get; set; } + } - public Category Category { get; set; } - } - public class Category - { - public int CategoryId { get; set; } - public string CategoryName { get; set; } - } + public class TrainingCourseDto + { + public int CourseId { get; set; } + public string CourseName { get; set; } - public class TrainingCourseDto - { - public int CourseId { get; set; } + public virtual IList Content { get; set; } + } - public string CourseName { get; set; } + public class CategoryDto + { + public int CategoryId { get; set; } + public string CategoryName { get; set; } + } - public virtual IList Content { get; set; } - } + public class TrainingContentDto + { + public int ContentId { get; set; } - public class CategoryDto - { - public int CategoryId { get; set; } - public string CategoryName { get; set; } - } + public string ContentName { get; set; } - public class TrainingContentDto - { - public int ContentId { get; set; } + public CategoryDto Category { get; set; } + } + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); - public string ContentName { get; set; } + await initializer.Migrate(); - public CategoryDto Category { get; set; } + using (var context = new ClientContext()) + { + _course = ProjectTo(context.TrainingCourses, null, "Content.Category").FirstOrDefault(n => n.CourseName == "Course 1"); } } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/ExplicitExpansion/ExpandMembersPath.cs b/src/IntegrationTests/ExplicitExpansion/ExpandMembersPath.cs index 28cd0adb58..8f015f4f04 100644 --- a/src/IntegrationTests/ExplicitExpansion/ExpandMembersPath.cs +++ b/src/IntegrationTests/ExplicitExpansion/ExpandMembersPath.cs @@ -1,156 +1,157 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -using System.Data.Entity; using System.Diagnostics; using System.Linq; -using AutoMapper.QueryableExtensions; +using System.Threading.Tasks; using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; using Shouldly; using Xunit; -namespace AutoMapper.IntegrationTests.Net4 +namespace AutoMapper.IntegrationTests.ExplicitExpansion; + +public class ExpandMembersPath : AutoMapperSpecBase, IAsyncLifetime { - public class ExpandMembersPath : AutoMapperSpecBase + protected override MapperConfiguration CreateConfiguration() => new(cfg => { - protected override MapperConfiguration CreateConfiguration() => new(cfg => + var mappingClass1 = cfg.CreateProjection(); + mappingClass1.ForMember(dest => dest.IdDTO, opt => opt.MapFrom(src => src.Id)); + mappingClass1.ForMember(dest => dest.NameDTO, opt => opt.MapFrom(src => src.Name)); + mappingClass1.ForMember(dest => dest.Class2DTO, opt => { - var mappingClass1 = cfg.CreateProjection(); - mappingClass1.ForMember(dest => dest.IdDTO, opt => opt.MapFrom(src => src.Id)); - mappingClass1.ForMember(dest => dest.NameDTO, opt => opt.MapFrom(src => src.Name)); - mappingClass1.ForMember(dest => dest.Class2DTO, opt => - { - opt.MapFrom(src => src.Class2); - opt.ExplicitExpansion(); - }); + opt.MapFrom(src => src.Class2); + opt.ExplicitExpansion(); + }); - var mappingClass2 = cfg.CreateProjection(); - mappingClass2.ForMember(dest => dest.IdDTO, opt => opt.MapFrom(src => src.Id)); - mappingClass2.ForMember(dest => dest.NameDTO, opt => opt.MapFrom(src => src.Name)); - mappingClass2.ForMember(dest => dest.Class3DTO, opt => - { - opt.MapFrom(src => src.Class3); - opt.ExplicitExpansion(); - }); + var mappingClass2 = cfg.CreateProjection(); + mappingClass2.ForMember(dest => dest.IdDTO, opt => opt.MapFrom(src => src.Id)); + mappingClass2.ForMember(dest => dest.NameDTO, opt => opt.MapFrom(src => src.Name)); + mappingClass2.ForMember(dest => dest.Class3DTO, opt => + { + opt.MapFrom(src => src.Class3); + opt.ExplicitExpansion(); + }); - var mappingClass3 = cfg.CreateProjection(); - mappingClass3.ForMember(dest => dest.IdDTO, opt => opt.MapFrom(src => src.Id)); - mappingClass3.ForMember(dest => dest.NameDTO, opt => opt.MapFrom(src => src.Name)); + var mappingClass3 = cfg.CreateProjection(); + mappingClass3.ForMember(dest => dest.IdDTO, opt => opt.MapFrom(src => src.Id)); + mappingClass3.ForMember(dest => dest.NameDTO, opt => opt.MapFrom(src => src.Name)); - //This is the trouble mapping - mappingClass3.ForMember(dest => dest.Class2DTO, opt => - { - opt.MapFrom(src => src.Class2); - opt.ExplicitExpansion(); - }); + //This is the trouble mapping + mappingClass3.ForMember(dest => dest.Class2DTO, opt => + { + opt.MapFrom(src => src.Class2); + opt.ExplicitExpansion(); }); + }); - [Fact] - public void Should_expand_all_members_in_path() + [Fact] + public void Should_expand_all_members_in_path() + { + Class1DTO[] dtos; + using(TestContext context = new TestContext()) { - Class1DTO[] dtos; - using(TestContext context = new TestContext()) - { - context.Database.Log = s => Debug.WriteLine(s); - dtos = ProjectTo(context.Class1Set, null, r => r.Class2DTO.Class3DTO).ToArray(); - } - Check(dtos); + dtos = ProjectTo(context.Class1Set, null, r => r.Class2DTO.Class3DTO).ToArray(); } + Check(dtos); + } - [Fact] - public void Should_expand_all_members_in_path_with_strings() + [Fact] + public void Should_expand_all_members_in_path_with_strings() + { + Class1DTO[] dtos; + using(TestContext context = new TestContext()) { - Class1DTO[] dtos; - using(TestContext context = new TestContext()) - { - context.Database.Log = s => Debug.WriteLine(s); - dtos = ProjectTo(context.Class1Set, null, "Class2DTO.Class3DTO").ToArray(); - } - Check(dtos); + dtos = ProjectTo(context.Class1Set, null, "Class2DTO.Class3DTO").ToArray(); } + Check(dtos); + } - private void Check(Class1DTO[] dtos) - { - dtos.Length.ShouldBe(3); - dtos.Select(d => d.IdDTO).ToArray().ShouldBe(new[] { 1, 2, 3 }); - dtos.Select(d => d.Class2DTO.IdDTO).ToArray().ShouldBe(new[] { 1, 2, 3 }); - dtos.Select(d => d.Class2DTO.Class3DTO.IdDTO).ToArray().ShouldBe(new[] { 1, 2, 3 }); - dtos.Select(d => d.Class2DTO.Class3DTO.Class2DTO).ToArray().ShouldBe(new Class2DTO[] { null, null, null }); - } + private void Check(Class1DTO[] dtos) + { + dtos.Length.ShouldBe(3); + dtos.Select(d => d.IdDTO).ToArray().ShouldBe(new[] { 1, 2, 3 }); + dtos.Select(d => d.Class2DTO.IdDTO).ToArray().ShouldBe(new[] { 1, 2, 3 }); + dtos.Select(d => d.Class2DTO.Class3DTO.IdDTO).ToArray().ShouldBe(new[] { 1, 2, 3 }); + dtos.Select(d => d.Class2DTO.Class3DTO.Class2DTO).ToArray().ShouldBe(new Class2DTO[] { null, null, null }); + } - public class TestContext : System.Data.Entity.DbContext - { - public TestContext() - { - Database.SetInitializer(new DatabaseInitializer()); - } - public DbSet Class1Set { get; set; } - public DbSet Class2Set { get; set; } - public DbSet Class3Set { get; set; } - } + public class TestContext : LocalDbContext + { + public DbSet Class1Set { get; set; } + public DbSet Class2Set { get; set; } + public DbSet Class3Set { get; set; } + } - public class DatabaseInitializer : CreateDatabaseIfNotExists + public class DatabaseInitializer : CreateDatabaseIfNotExists + { + protected override void Seed(TestContext context) { - protected override void Seed(TestContext context) + context.Class1Set.AddRange(new[] { - context.Class1Set.AddRange(new[] - { - new Class1 { Class2 = new Class2 { Class3 = new Class3 { Name = "SomeValue" }}, Name = "Alain Brito"}, - new Class1 { Class2 = new Class2 { Class3 = new Class3 { Name = "OtherValue" }}, Name = "Jimmy Bogard"}, - new Class1 { Class2 = new Class2 { Class3 = new Class3 { Name = "SomeValue" }}, Name = "Bill Gates"} - }); - base.Seed(context); - } + new Class1 { Class2 = new Class2 { Class3 = new Class3 { Name = "SomeValue" }}, Name = "Alain Brito"}, + new Class1 { Class2 = new Class2 { Class3 = new Class3 { Name = "OtherValue" }}, Name = "Jimmy Bogard"}, + new Class1 { Class2 = new Class2 { Class3 = new Class3 { Name = "SomeValue" }}, Name = "Bill Gates"} + }); + base.Seed(context); } + } - public class Class1DTO - { - public int IdDTO { get; set; } - public string NameDTO { get; set; } + public class Class1DTO + { + public int IdDTO { get; set; } + public string NameDTO { get; set; } - public Class2DTO Class2DTO { get; set; } - } + public Class2DTO Class2DTO { get; set; } + } - public class Class2DTO - { - public int IdDTO { get; set; } - public string NameDTO { get; set; } + public class Class2DTO + { + public int IdDTO { get; set; } + public string NameDTO { get; set; } - public Class3DTO Class3DTO { get; set; } - } + public Class3DTO Class3DTO { get; set; } + } - public class Class3DTO - { - public int IdDTO { get; set; } - public string NameDTO { get; set; } + public class Class3DTO + { + public int IdDTO { get; set; } + public string NameDTO { get; set; } - public Class2DTO Class2DTO { get; set; } - } + public Class2DTO Class2DTO { get; set; } + } - public class Class1 - { - [Key] - public int Id { get; set; } - public string Name { get; set; } + public class Class1 + { + [Key] + public int Id { get; set; } + public string Name { get; set; } - public Class2 Class2 { get; set; } - } + public Class2 Class2 { get; set; } + } - public class Class2 - { - [Key] - public int Id { get; set; } - public string Name { get; set; } + public class Class2 + { + [Key] + public int Id { get; set; } + public string Name { get; set; } - public Class3 Class3 { get; set; } - } + public Class3 Class3 { get; set; } + } - public class Class3 - { - [Key, ForeignKeyAttribute("Class2")] - public int Id { get; set; } - public string Name { get; set; } + public class Class3 + { + [Key, ForeignKey("Class2")] + public int Id { get; set; } + public string Name { get; set; } - public Class2 Class2 { get; set; } - } + public Class2 Class2 { get; set; } } + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/ExplicitExpansion/ExplicitlyExpandCollectionsAndChildReferences.cs b/src/IntegrationTests/ExplicitExpansion/ExplicitlyExpandCollectionsAndChildReferences.cs index 8eab2d6416..3d00d8d3b2 100644 --- a/src/IntegrationTests/ExplicitExpansion/ExplicitlyExpandCollectionsAndChildReferences.cs +++ b/src/IntegrationTests/ExplicitExpansion/ExplicitlyExpandCollectionsAndChildReferences.cs @@ -1,114 +1,113 @@ -using AutoMapper.UnitTests; -using Shouldly; -using System.Collections.Generic; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.Data.Entity; using System.Diagnostics; using System.Linq; +using System.Threading.Tasks; +using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; +using Shouldly; using Xunit; -namespace AutoMapper.IntegrationTests.Net4 +namespace AutoMapper.IntegrationTests.ExplicitExpansion; + +public class ExplicitlyExpandCollectionsAndChildReferences : AutoMapperSpecBase, IAsyncLifetime { - public class ExplicitlyExpandCollectionsAndChildReferences : AutoMapperSpecBase + TrainingCourseDto _course; + + protected override MapperConfiguration CreateConfiguration() => new(cfg => { - TrainingCourseDto _course; + cfg.CreateProjection(); + cfg.CreateProjection().ForMember(c => c.Content, o => o.ExplicitExpansion()); + cfg.CreateProjection().ForMember(c => c.Category, o => o.ExplicitExpansion()); + }); - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection(); - cfg.CreateProjection().ForMember(c => c.Content, o => o.ExplicitExpansion()); - cfg.CreateProjection().ForMember(c => c.Category, o => o.ExplicitExpansion()); - }); + [Fact] + public void Should_expand_collections_items() + { + _course.Content[0].Category.CategoryName.ShouldBe("Category 1"); + } - protected override void Because_of() + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(ClientContext context) { - using (var context = new ClientContext()) - { - context.Database.Log = s => Trace.WriteLine(s); - _course = ProjectTo(context.TrainingCourses, null, c => c.Content.Select(co => co.Category)).FirstOrDefault(n => n.CourseName == "Course 1"); - } + var category = new Category { CategoryName = "Category 1" }; + var course = new TrainingCourse { CourseName = "Course 1" }; + context.TrainingCourses.Add(course); + var content = new TrainingContent { ContentName = "Content 1", Category = category }; + context.TrainingContents.Add(content); + course.Content.Add(content); } + } + class ClientContext : LocalDbContext + { + public DbSet Categories { get; set; } + public DbSet TrainingCourses { get; set; } + public DbSet TrainingContents { get; set; } + } - [Fact] - public void Should_expand_collections_items() - { - _course.Content[0].Category.CategoryName.ShouldBe("Category 1"); - } - - class Initializer : DropCreateDatabaseAlways - { - protected override void Seed(ClientContext context) - { - var category = new Category { CategoryName = "Category 1" }; - var course = new TrainingCourse { CourseName = "Course 1" }; - context.TrainingCourses.Add(course); - var content = new TrainingContent { ContentName = "Content 1", Category = category }; - context.TrainingContents.Add(content); - course.Content.Add(content); - } - } + public class TrainingCourse + { + [Key] + public int CourseId { get; set; } - class ClientContext : DbContext - { - public ClientContext() - { - Database.SetInitializer(new Initializer()); - } - public DbSet Categories { get; set; } - public DbSet TrainingCourses { get; set; } - public DbSet TrainingContents { get; set; } - } + public string CourseName { get; set; } - public class TrainingCourse - { - [Key] - public int CourseId { get; set; } + public virtual IList Content { get; set; } = new List(); + } - public string CourseName { get; set; } + public class TrainingContent + { + [Key] + public int ContentId { get; set; } - public virtual IList Content { get; set; } = new List(); - } + public string ContentName { get; set; } - public class TrainingContent - { - [Key] - public int ContentId { get; set; } + public Category Category { get; set; } + } - public string ContentName { get; set; } + public class Category + { + public int CategoryId { get; set; } + public string CategoryName { get; set; } + } - public Category Category { get; set; } - } - public class Category - { - public int CategoryId { get; set; } - public string CategoryName { get; set; } - } + public class TrainingCourseDto + { + public int CourseId { get; set; } + public string CourseName { get; set; } - public class TrainingCourseDto - { - public int CourseId { get; set; } + public virtual IList Content { get; set; } + } - public string CourseName { get; set; } + public class CategoryDto + { + public int CategoryId { get; set; } + public string CategoryName { get; set; } + } - public virtual IList Content { get; set; } - } + public class TrainingContentDto + { + public int ContentId { get; set; } - public class CategoryDto - { - public int CategoryId { get; set; } - public string CategoryName { get; set; } - } + public string ContentName { get; set; } - public class TrainingContentDto - { - public int ContentId { get; set; } + public CategoryDto Category { get; set; } + } + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); - public string ContentName { get; set; } + await initializer.Migrate(); - public CategoryDto Category { get; set; } + using (var context = new ClientContext()) + { + _course = ProjectTo(context.TrainingCourses, null, c => c.Content.Select(co => co.Category)).FirstOrDefault(n => n.CourseName == "Course 1"); } } -} + + public Task DisposeAsync() => Task.CompletedTask; +} \ No newline at end of file diff --git a/src/IntegrationTests/ExplicitExpansion/MembersToExpandExpressions.cs b/src/IntegrationTests/ExplicitExpansion/MembersToExpandExpressions.cs index 5cf1a36c18..4e1eed4969 100644 --- a/src/IntegrationTests/ExplicitExpansion/MembersToExpandExpressions.cs +++ b/src/IntegrationTests/ExplicitExpansion/MembersToExpandExpressions.cs @@ -1,66 +1,74 @@ -using System.Data.Entity; -using System.Linq; +using System.Linq; +using System.Threading.Tasks; +using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; using Shouldly; using Xunit; -namespace AutoMapper.UnitTests.Projection +namespace AutoMapper.IntegrationTests.ExplicitExpansion; + +public class MembersToExpandExpressions : AutoMapperSpecBase, IAsyncLifetime { - public class MembersToExpandExpressions : AutoMapperSpecBase + public class SourceDeepInner { - public class SourceDeepInner - { - public int Desc { get; set; } - public int Id { get; set; } - } - public class SourceInner - { - public int Id { get; set; } - public int Desc { get; set; } - public SourceDeepInner Deep { get; set; } - } - public class Source - { - public int Id { get; set; } - public string Name { get; set; } - public int Desc { get; set; } - public SourceInner Inner { get; set; } - } - public class Dto - { - public string Name { get; set; } - public int? Desc { get; set; } - public int? InnerDescFlattened { get; set; } - public int? DeepFlattened { get; set; } - } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - cfg.CreateProjection() - .ForMember(dto => dto.InnerDescFlattened, conf => { conf.ExplicitExpansion(); conf.MapFrom(_ => _.Inner .Desc); }) - .ForMember(dto => dto. DeepFlattened, conf => { conf.ExplicitExpansion(); conf.MapFrom(_ => _.Inner.Deep.Desc); })); - public class TestContext : DbContext - { - public TestContext() : base() => Database.SetInitializer(new DatabaseInitializer()); - public DbSet Sources { get; set; } - } - static Source _source = new Source() { Name = "Name1", Desc = -12, Inner = new SourceInner { Desc = -25, Deep = new SourceDeepInner() { Desc = 28 } } }; - public class DatabaseInitializer : DropCreateDatabaseAlways + public int Desc { get; set; } + public int Id { get; set; } + } + public class SourceInner + { + public int Id { get; set; } + public int Desc { get; set; } + public SourceDeepInner Deep { get; set; } + } + public class Source + { + public int Id { get; set; } + public string Name { get; set; } + public int Desc { get; set; } + public SourceInner Inner { get; set; } + } + public class Dto + { + public string Name { get; set; } + public int? Desc { get; set; } + public int? InnerDescFlattened { get; set; } + public int? DeepFlattened { get; set; } + } + protected override MapperConfiguration CreateConfiguration() => new(cfg => + cfg.CreateProjection() + .ForMember(dto => dto.InnerDescFlattened, conf => { conf.ExplicitExpansion(); conf.MapFrom(_ => _.Inner .Desc); }) + .ForMember(dto => dto. DeepFlattened, conf => { conf.ExplicitExpansion(); conf.MapFrom(_ => _.Inner.Deep.Desc); })); + public class TestContext : LocalDbContext + { + public DbSet Sources { get; set; } + } + static Source _source = new Source() { Name = "Name1", Desc = -12, Inner = new SourceInner { Desc = -25, Deep = new SourceDeepInner() { Desc = 28 } } }; + public class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(TestContext testContext) { - protected override void Seed(TestContext testContext) - { - testContext.Sources.Add(_source); - base.Seed(testContext); - } + testContext.Sources.Add(_source); + base.Seed(testContext); } - [Fact] - public void Should_project_ok() + } + [Fact] + public void Should_project_ok() + { + using (var context = new TestContext()) { - using (var context = new TestContext()) - { - ProjectTo(context.Sources, null, _ => _.Name).First().Name.ShouldBe(_source.Name); - ProjectTo(context.Sources, null, _ => _.Desc).First().Desc.ShouldBe(_source.Desc); - ProjectTo(context.Sources, null, _ => _.Name, _ => _.Desc); - ProjectTo(context.Sources, null, _ => _.InnerDescFlattened).First().InnerDescFlattened.ShouldBe(_source.Inner.Desc); - ProjectTo(context.Sources, null, _ => _.DeepFlattened).First().DeepFlattened.ShouldBe(_source.Inner.Deep.Desc); - } + ProjectTo(context.Sources, null, _ => _.Name).First().Name.ShouldBe(_source.Name); + ProjectTo(context.Sources, null, _ => _.Desc).First().Desc.ShouldBe(_source.Desc); + ProjectTo(context.Sources, null, _ => _.Name, _ => _.Desc); + ProjectTo(context.Sources, null, _ => _.InnerDescFlattened).First().InnerDescFlattened.ShouldBe(_source.Inner.Desc); + ProjectTo(context.Sources, null, _ => _.DeepFlattened).First().DeepFlattened.ShouldBe(_source.Inner.Deep.Desc); } } + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/ExplicitExpansion/NestedExplicitExpand.cs b/src/IntegrationTests/ExplicitExpansion/NestedExplicitExpand.cs index 9b4990435f..61dbf654d2 100644 --- a/src/IntegrationTests/ExplicitExpansion/NestedExplicitExpand.cs +++ b/src/IntegrationTests/ExplicitExpansion/NestedExplicitExpand.cs @@ -1,157 +1,155 @@ -using System; -using System.Data.Entity; -using System.Data.Entity.Migrations; -using System.Diagnostics; +using System.Diagnostics; using System.Linq; -using System.Linq.Expressions; -using AutoMapper.QueryableExtensions; +using System.Threading.Tasks; using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; using Shouldly; using Xunit; -namespace AutoMapper.IntegrationTests.Net4 +namespace AutoMapper.IntegrationTests.ExplicitExpansion; + +public class NestedExplicitExpand : AutoMapperSpecBase, IAsyncLifetime { - public class NestedExplicitExpand : AutoMapperSpecBase + protected override MapperConfiguration CreateConfiguration() => new(cfg => { - protected override MapperConfiguration CreateConfiguration() => new(cfg => + var mappingClass1 = cfg.CreateProjection(); + mappingClass1.ForMember(dest => dest.IdDTO, opt => opt.MapFrom(src => src.Id)); + mappingClass1.ForMember(dest => dest.NameDTO, opt => opt.MapFrom(src => src.Name)); + mappingClass1.ForMember(dest => dest.Class2DTO, opt => { - var mappingClass1 = cfg.CreateProjection(); - mappingClass1.ForMember(dest => dest.IdDTO, opt => opt.MapFrom(src => src.Id)); - mappingClass1.ForMember(dest => dest.NameDTO, opt => opt.MapFrom(src => src.Name)); - mappingClass1.ForMember(dest => dest.Class2DTO, opt => - { - opt.MapFrom(src => src.Class2); - opt.ExplicitExpansion(); - }); + opt.MapFrom(src => src.Class2); + opt.ExplicitExpansion(); + }); - var mappingClass2 = cfg.CreateProjection(); - mappingClass2.ForMember(dest => dest.IdDTO, opt => opt.MapFrom(src => src.Id)); - mappingClass2.ForMember(dest => dest.NameDTO, opt => opt.MapFrom(src => src.Name)); - mappingClass2.ForMember(dest => dest.Class3DTO, opt => - { - opt.MapFrom(src => src.Class3); - opt.ExplicitExpansion(); - }); + var mappingClass2 = cfg.CreateProjection(); + mappingClass2.ForMember(dest => dest.IdDTO, opt => opt.MapFrom(src => src.Id)); + mappingClass2.ForMember(dest => dest.NameDTO, opt => opt.MapFrom(src => src.Name)); + mappingClass2.ForMember(dest => dest.Class3DTO, opt => + { + opt.MapFrom(src => src.Class3); + opt.ExplicitExpansion(); + }); - var mappingClass3 = cfg.CreateProjection(); - mappingClass3.ForMember(dest => dest.IdDTO, opt => opt.MapFrom(src => src.Id)); - mappingClass3.ForMember(dest => dest.NameDTO, opt => opt.MapFrom(src => src.Name)); + var mappingClass3 = cfg.CreateProjection(); + mappingClass3.ForMember(dest => dest.IdDTO, opt => opt.MapFrom(src => src.Id)); + mappingClass3.ForMember(dest => dest.NameDTO, opt => opt.MapFrom(src => src.Name)); - //This is the trouble mapping - mappingClass3.ForMember(dest => dest.Class2DTO, opt => - { - opt.MapFrom(src => src.Class2); - opt.ExplicitExpansion(); - }); + //This is the trouble mapping + mappingClass3.ForMember(dest => dest.Class2DTO, opt => + { + opt.MapFrom(src => src.Class2); + opt.ExplicitExpansion(); }); + }); - [Fact] - public void Should_handle_nested_explicit_expand_with_expressions() + [Fact] + public void Should_handle_nested_explicit_expand_with_expressions() + { + Class1DTO[] dtos; + using(TestContext context = new TestContext()) { - Class1DTO[] dtos; - using(TestContext context = new TestContext()) - { - context.Database.Log = s => Debug.WriteLine(s); - dtos = ProjectTo(context.Class1Set, null, r => r.Class2DTO, r => r.Class2DTO.Class3DTO).ToArray(); - } - Check(dtos); + dtos = ProjectTo(context.Class1Set, null, r => r.Class2DTO, r => r.Class2DTO.Class3DTO).ToArray(); } + Check(dtos); + } - [Fact] - public void Should_handle_nested_explicit_expand_with_strings() + [Fact] + public void Should_handle_nested_explicit_expand_with_strings() + { + Class1DTO[] dtos; + using(TestContext context = new TestContext()) { - Class1DTO[] dtos; - using(TestContext context = new TestContext()) - { - context.Database.Log = s => Debug.WriteLine(s); - dtos = ProjectTo(context.Class1Set, null, "Class2DTO", "Class2DTO.Class3DTO").ToArray(); - } - Check(dtos); + dtos = ProjectTo(context.Class1Set, null, "Class2DTO", "Class2DTO.Class3DTO").ToArray(); } + Check(dtos); + } - private void Check(Class1DTO[] dtos) - { - dtos.Length.ShouldBe(3); - dtos.Select(d => d.IdDTO).ShouldBe(new[] { 1, 2, 3 }); - dtos.Select(d => d.Class2DTO.IdDTO).ShouldBe(new[] { 1, 2, 3 }); - dtos.Select(d => d.Class2DTO.Class3DTO.IdDTO).ShouldBe(new[] { 1, 2, 3 }); - dtos.Select(d => d.Class2DTO.Class3DTO.Class2DTO).ShouldBe(new Class2DTO[] { null, null, null }); - } + private void Check(Class1DTO[] dtos) + { + dtos.Length.ShouldBe(3); + dtos.Select(d => d.IdDTO).ShouldBe(new[] { 1, 2, 3 }); + dtos.Select(d => d.Class2DTO.IdDTO).ShouldBe(new[] { 1, 2, 3 }); + dtos.Select(d => d.Class2DTO.Class3DTO.IdDTO).ShouldBe(new[] { 1, 2, 3 }); + dtos.Select(d => d.Class2DTO.Class3DTO.Class2DTO).ShouldBe(new Class2DTO[] { null, null, null }); + } - public class TestContext : System.Data.Entity.DbContext - { - public TestContext() - { - Database.SetInitializer(new DatabaseInitializer()); - } - public DbSet Class1Set { get; set; } - public DbSet Class2Set { get; set; } - public DbSet Class3Set { get; set; } - } + public class TestContext : LocalDbContext + { + public DbSet Class1Set { get; set; } + public DbSet Class2Set { get; set; } + public DbSet Class3Set { get; set; } + } - public class DatabaseInitializer : CreateDatabaseIfNotExists + public class DatabaseInitializer : CreateDatabaseIfNotExists + { + protected override void Seed(TestContext context) { - protected override void Seed(TestContext context) + context.Class1Set.AddRange(new[] { - context.Class1Set.AddRange(new[] - { - new Class1 { Class2 = new Class2 { Class3 = new Class3 { Name = "SomeValue" }}, Name = "Alain Brito"}, - new Class1 { Class2 = new Class2 { Class3 = new Class3 { Name = "OtherValue" }}, Name = "Jimmy Bogard"}, - new Class1 { Class2 = new Class2 { Class3 = new Class3 { Name = "SomeValue" }}, Name = "Bill Gates"} - }); - base.Seed(context); - } + new Class1 { Class2 = new Class2 { Class3 = new Class3 { Name = "SomeValue" }}, Name = "Alain Brito"}, + new Class1 { Class2 = new Class2 { Class3 = new Class3 { Name = "OtherValue" }}, Name = "Jimmy Bogard"}, + new Class1 { Class2 = new Class2 { Class3 = new Class3 { Name = "SomeValue" }}, Name = "Bill Gates"} + }); + base.Seed(context); } + } - public class Class1DTO - { - public int IdDTO { get; set; } - public string NameDTO { get; set; } + public class Class1DTO + { + public int IdDTO { get; set; } + public string NameDTO { get; set; } - public Class2DTO Class2DTO { get; set; } - } + public Class2DTO Class2DTO { get; set; } + } - public class Class2DTO - { - public int IdDTO { get; set; } - public string NameDTO { get; set; } + public class Class2DTO + { + public int IdDTO { get; set; } + public string NameDTO { get; set; } - public Class3DTO Class3DTO { get; set; } - } + public Class3DTO Class3DTO { get; set; } + } - public class Class3DTO - { - public int IdDTO { get; set; } - public string NameDTO { get; set; } + public class Class3DTO + { + public int IdDTO { get; set; } + public string NameDTO { get; set; } - public Class2DTO Class2DTO { get; set; } - } + public Class2DTO Class2DTO { get; set; } + } - public class Class1 - { - [System.ComponentModel.DataAnnotations.Key] - public int Id { get; set; } - public string Name { get; set; } + public class Class1 + { + [System.ComponentModel.DataAnnotations.Key] + public int Id { get; set; } + public string Name { get; set; } - public Class2 Class2 { get; set; } - } + public Class2 Class2 { get; set; } + } - public class Class2 - { - [System.ComponentModel.DataAnnotations.Key] - public int Id { get; set; } - public string Name { get; set; } + public class Class2 + { + [System.ComponentModel.DataAnnotations.Key] + public int Id { get; set; } + public string Name { get; set; } - public Class3 Class3 { get; set; } - } + public Class3 Class3 { get; set; } + } - public class Class3 - { - [System.ComponentModel.DataAnnotations.Key, System.ComponentModel.DataAnnotations.Schema.ForeignKeyAttribute("Class2")] - public int Id { get; set; } - public string Name { get; set; } + public class Class3 + { + [System.ComponentModel.DataAnnotations.Key, System.ComponentModel.DataAnnotations.Schema.ForeignKeyAttribute("Class2")] + public int Id { get; set; } + public string Name { get; set; } - public Class2 Class2 { get; set; } - } + public Class2 Class2 { get; set; } } + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/ExplicitExpansion/NestedExplicitExpandWithFields.cs b/src/IntegrationTests/ExplicitExpansion/NestedExplicitExpandWithFields.cs index 6fd538f35a..75229f95ad 100644 --- a/src/IntegrationTests/ExplicitExpansion/NestedExplicitExpandWithFields.cs +++ b/src/IntegrationTests/ExplicitExpansion/NestedExplicitExpandWithFields.cs @@ -1,157 +1,156 @@ -using System; -using System.Data.Entity; -using System.Data.Entity.Migrations; -using System.Diagnostics; +using System.Diagnostics; using System.Linq; -using System.Linq.Expressions; -using AutoMapper.QueryableExtensions; +using System.Threading.Tasks; using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; using Shouldly; using Xunit; -namespace AutoMapper.IntegrationTests.Net4 +namespace AutoMapper.IntegrationTests.ExplicitExpansion; + +public class NestedExplicitExpandWithFields : AutoMapperSpecBase, IAsyncLifetime { - public class NestedExplicitExpandWithFields : AutoMapperSpecBase + protected override MapperConfiguration CreateConfiguration() => new(cfg => { - protected override MapperConfiguration CreateConfiguration() => new(cfg => + var mappingClass1 = cfg.CreateProjection(); + mappingClass1.ForMember(dest => dest.IdDTO, opt => opt.MapFrom(src => src.Id)); + mappingClass1.ForMember(dest => dest.NameDTO, opt => opt.MapFrom(src => src.Name)); + mappingClass1.ForMember(dest => dest.Class2DTO, opt => { - var mappingClass1 = cfg.CreateProjection(); - mappingClass1.ForMember(dest => dest.IdDTO, opt => opt.MapFrom(src => src.Id)); - mappingClass1.ForMember(dest => dest.NameDTO, opt => opt.MapFrom(src => src.Name)); - mappingClass1.ForMember(dest => dest.Class2DTO, opt => - { - opt.MapFrom(src => src.Class2); - opt.ExplicitExpansion(); - }); + opt.MapFrom(src => src.Class2); + opt.ExplicitExpansion(); + }); - var mappingClass2 = cfg.CreateProjection(); - mappingClass2.ForMember(dest => dest.IdDTO, opt => opt.MapFrom(src => src.Id)); - mappingClass2.ForMember(dest => dest.NameDTO, opt => opt.MapFrom(src => src.Name)); - mappingClass2.ForMember(dest => dest.Class3DTO, opt => - { - opt.MapFrom(src => src.Class3); - opt.ExplicitExpansion(); - }); + var mappingClass2 = cfg.CreateProjection(); + mappingClass2.ForMember(dest => dest.IdDTO, opt => opt.MapFrom(src => src.Id)); + mappingClass2.ForMember(dest => dest.NameDTO, opt => opt.MapFrom(src => src.Name)); + mappingClass2.ForMember(dest => dest.Class3DTO, opt => + { + opt.MapFrom(src => src.Class3); + opt.ExplicitExpansion(); + }); - var mappingClass3 = cfg.CreateProjection(); - mappingClass3.ForMember(dest => dest.IdDTO, opt => opt.MapFrom(src => src.Id)); - mappingClass3.ForMember(dest => dest.NameDTO, opt => opt.MapFrom(src => src.Name)); + var mappingClass3 = cfg.CreateProjection(); + mappingClass3.ForMember(dest => dest.IdDTO, opt => opt.MapFrom(src => src.Id)); + mappingClass3.ForMember(dest => dest.NameDTO, opt => opt.MapFrom(src => src.Name)); - //This is the trouble mapping - mappingClass3.ForMember(dest => dest.Class2DTO, opt => - { - opt.MapFrom(src => src.Class2); - opt.ExplicitExpansion(); - }); + //This is the trouble mapping + mappingClass3.ForMember(dest => dest.Class2DTO, opt => + { + opt.MapFrom(src => src.Class2); + opt.ExplicitExpansion(); }); + }); - [Fact] - public void Should_handle_nested_explicit_expand_with_expressions() + [Fact] + public void Should_handle_nested_explicit_expand_with_expressions() + { + Class1DTO[] dtos; + using(TestContext context = new TestContext()) { - Class1DTO[] dtos; - using(TestContext context = new TestContext()) - { - context.Database.Log = s => Debug.WriteLine(s); - dtos = ProjectTo(context.Class1Set, null, r => r.Class2DTO, r => r.Class2DTO.Class3DTO).ToArray(); - } - Check(dtos); + dtos = ProjectTo(context.Class1Set, null, r => r.Class2DTO, r => r.Class2DTO.Class3DTO).ToArray(); } + Check(dtos); + } - [Fact] - public void Should_handle_nested_explicit_expand_with_strings() + [Fact] + public void Should_handle_nested_explicit_expand_with_strings() + { + Class1DTO[] dtos; + using(TestContext context = new TestContext()) { - Class1DTO[] dtos; - using(TestContext context = new TestContext()) - { - context.Database.Log = s => Debug.WriteLine(s); - dtos = ProjectTo(context.Class1Set, null, "Class2DTO", "Class2DTO.Class3DTO").ToArray(); - } - Check(dtos); + dtos = ProjectTo(context.Class1Set, null, "Class2DTO", "Class2DTO.Class3DTO").ToArray(); } + Check(dtos); + } - private void Check(Class1DTO[] dtos) - { - dtos.Length.ShouldBe(3); - dtos.Select(d => d.IdDTO).ShouldBe(new[] { 1, 2, 3 }); - dtos.Select(d => d.Class2DTO.IdDTO).ShouldBe(new[] { 1, 2, 3 }); - dtos.Select(d => d.Class2DTO.Class3DTO.IdDTO).ShouldBe(new[] { 1, 2, 3 }); - dtos.Select(d => d.Class2DTO.Class3DTO.Class2DTO).ShouldBe(new Class2DTO[] { null, null, null }); - } + private void Check(Class1DTO[] dtos) + { + dtos.Length.ShouldBe(3); + dtos.Select(d => d.IdDTO).ShouldBe(new[] { 1, 2, 3 }); + dtos.Select(d => d.Class2DTO.IdDTO).ShouldBe(new[] { 1, 2, 3 }); + dtos.Select(d => d.Class2DTO.Class3DTO.IdDTO).ShouldBe(new[] { 1, 2, 3 }); + dtos.Select(d => d.Class2DTO.Class3DTO.Class2DTO).ShouldBe(new Class2DTO[] { null, null, null }); + } - public class TestContext : System.Data.Entity.DbContext - { - public TestContext() - { - Database.SetInitializer(new DatabaseInitializer()); - } - public DbSet Class1Set { get; set; } - public DbSet Class2Set { get; set; } - public DbSet Class3Set { get; set; } - } + public class TestContext : LocalDbContext + { + public DbSet Class1Set { get; set; } + public DbSet Class2Set { get; set; } + public DbSet Class3Set { get; set; } + } - public class DatabaseInitializer : CreateDatabaseIfNotExists + public class DatabaseInitializer : CreateDatabaseIfNotExists + { + protected override void Seed(TestContext context) { - protected override void Seed(TestContext context) + context.Class1Set.AddRange(new[] { - context.Class1Set.AddRange(new[] - { - new Class1 { Class2 = new Class2 { Class3 = new Class3 { Name = "SomeValue" }}, Name = "Alain Brito"}, - new Class1 { Class2 = new Class2 { Class3 = new Class3 { Name = "OtherValue" }}, Name = "Jimmy Bogard"}, - new Class1 { Class2 = new Class2 { Class3 = new Class3 { Name = "SomeValue" }}, Name = "Bill Gates"} - }); - base.Seed(context); - } + new Class1 { Class2 = new Class2 { Class3 = new Class3 { Name = "SomeValue" }}, Name = "Alain Brito"}, + new Class1 { Class2 = new Class2 { Class3 = new Class3 { Name = "OtherValue" }}, Name = "Jimmy Bogard"}, + new Class1 { Class2 = new Class2 { Class3 = new Class3 { Name = "SomeValue" }}, Name = "Bill Gates"} + }); + base.Seed(context); } + } - public class Class1DTO - { - public int IdDTO; - public string NameDTO; + public class Class1DTO + { + public int IdDTO; + public string NameDTO; - public Class2DTO Class2DTO; - } + public Class2DTO Class2DTO; + } - public class Class2DTO - { - public int IdDTO; - public string NameDTO; + public class Class2DTO + { + public int IdDTO; + public string NameDTO; - public Class3DTO Class3DTO; - } + public Class3DTO Class3DTO; + } - public class Class3DTO - { - public int IdDTO; - public string NameDTO; + public class Class3DTO + { + public int IdDTO; + public string NameDTO; - public Class2DTO Class2DTO; - } + public Class2DTO Class2DTO; + } - public class Class1 - { - [System.ComponentModel.DataAnnotations.Key] - public int Id { get; set; } - public string Name { get; set; } + public class Class1 + { + [System.ComponentModel.DataAnnotations.Key] + public int Id { get; set; } + public string Name { get; set; } - public Class2 Class2 { get; set; } - } + public Class2 Class2 { get; set; } + } - public class Class2 - { - [System.ComponentModel.DataAnnotations.Key] - public int Id { get; set; } - public string Name { get; set; } + public class Class2 + { + [System.ComponentModel.DataAnnotations.Key] + public int Id { get; set; } + public string Name { get; set; } - public Class3 Class3 { get; set; } - } + public Class3 Class3 { get; set; } + } - public class Class3 - { - [System.ComponentModel.DataAnnotations.Key, System.ComponentModel.DataAnnotations.Schema.ForeignKeyAttribute("Class2")] - public int Id { get; set; } - public string Name { get; set; } + public class Class3 + { + [System.ComponentModel.DataAnnotations.Key, System.ComponentModel.DataAnnotations.Schema.ForeignKeyAttribute("Class2")] + public int Id { get; set; } + public string Name { get; set; } - public Class2 Class2 { get; set; } - } + public Class2 Class2 { get; set; } } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/ExplicitExpansion/ProjectAndAllowNullCollections.cs b/src/IntegrationTests/ExplicitExpansion/ProjectAndAllowNullCollections.cs index 03ae4930d1..41ad64150b 100644 --- a/src/IntegrationTests/ExplicitExpansion/ProjectAndAllowNullCollections.cs +++ b/src/IntegrationTests/ExplicitExpansion/ProjectAndAllowNullCollections.cs @@ -1,148 +1,149 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Data.Entity; +using System.Collections.Generic; using System.Linq; -using Xunit; +using System.Threading.Tasks; +using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; using Shouldly; +using Xunit; -namespace AutoMapper.IntegrationTests.Net4 -{ - using UnitTests; - using QueryableExtensions; - using System.Data.Entity.ModelConfiguration; +namespace AutoMapper.IntegrationTests.ExplicitExpansion; - public class ProjectAndAllowNullCollections : AutoMapperSpecBase +public class ProjectAndAllowNullCollections : AutoMapperSpecBase, IAsyncLifetime +{ + public class Foo { - public class Foo - { - public virtual int ID { get; set; } + public virtual int ID { get; set; } - public virtual ISet Bars { get; } = new HashSet(); + public virtual ISet Bars { get; } = new HashSet(); - public virtual ISet Bazs { get; } = new HashSet(); - } + public virtual ISet Bazs { get; } = new HashSet(); + } - public class Bar - { - public virtual int ID { get; set; } + public class Bar + { + public virtual int ID { get; set; } - public virtual string Value { get; set; } - } + public virtual string Value { get; set; } - public class Baz - { - public virtual int ID { get; set; } + public virtual ISet Foos { get; } = new HashSet(); + } - public virtual string Value { get; set; } - } + public class Baz + { + public virtual int ID { get; set; } - public class FooDto - { - public int ID { get; set; } + public virtual string Value { get; set; } + public virtual ISet Foos { get; } = new HashSet(); + } - public List Bars { get; set; } + public class FooDto + { + public int ID { get; set; } - public List Bazs { get; set; } - } + public List Bars { get; set; } - public class BarDto - { - public int ID { get; set; } + public List Bazs { get; set; } + } - public string Value { get; set; } - } + public class BarDto + { + public int ID { get; set; } - public class BazDto - { - public int ID { get; set; } + public string Value { get; set; } + } - public string Value { get; set; } - } + public class BazDto + { + public int ID { get; set; } - public class MyContextInitializer : DropCreateDatabaseAlways - { - public override void InitializeDatabase(MyContext context) - { - base.InitializeDatabase(context); + public string Value { get; set; } + } - var foo1 = new Foo(); - var foo2 = new Foo(); // { Bars = new List() }; - var foo3 = new Foo(); // { Bars = new List() }; + public class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(MyContext context) + { + var foo1 = new Foo(); + var foo2 = new Foo(); // { Bars = new List() }; + var foo3 = new Foo(); // { Bars = new List() }; - context.Foos.Add(foo1); - context.Foos.Add(foo2); - context.Foos.Add(foo3); + context.Foos.Add(foo1); + context.Foos.Add(foo2); + context.Foos.Add(foo3); - context.SaveChanges(); + context.SaveChanges(); - var bar1 = new Bar { Value = "bar1" }; - var bar2 = new Bar { Value = "bar2" }; + var bar1 = new Bar { Value = "bar1" }; + var bar2 = new Bar { Value = "bar2" }; - foo2.Bars.Add(bar1); + foo2.Bars.Add(bar1); - foo3.Bars.Add(bar1); - foo3.Bars.Add(bar2); + foo3.Bars.Add(bar1); + foo3.Bars.Add(bar2); - context.Bars.Add(bar1); - context.Bars.Add(bar2); + context.Bars.Add(bar1); + context.Bars.Add(bar2); - context.SaveChanges(); - } + context.SaveChanges(); } + } - public class MyContext : DbContext - { - public MyContext() : base("AutomapperNullCollections") - { - Database.SetInitializer(new MyContextInitializer()); - } - - public DbSet Foos { get; set; } + public class MyContext : LocalDbContext + { + public DbSet Foos { get; set; } - public DbSet Bars { get; set; } + public DbSet Bars { get; set; } - public DbSet Bazs { get; set; } + public DbSet Bazs { get; set; } - protected override void OnModelCreating(DbModelBuilder modelBuilder) - { - base.OnModelCreating(modelBuilder); + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); - modelBuilder.Configurations.AddFromAssembly(typeof(MyContext).Assembly); - } + modelBuilder.ApplyConfigurationsFromAssembly(typeof(MyContext).Assembly); } + } - public class FooConfiguration : EntityTypeConfiguration + public class FooConfiguration : IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) { - public FooConfiguration() - { - HasMany(m => m.Bars).WithMany(); - HasMany(m => m.Bazs).WithMany(); - } + builder.HasMany(m => m.Bars).WithMany(b => b.Foos); + builder.HasMany(m => m.Bazs).WithMany(b => b.Foos); } + } - protected override MapperConfiguration CreateConfiguration() => new(c => - { - c.AllowNullCollections = true; + protected override MapperConfiguration CreateConfiguration() => new(c => + { + c.AllowNullCollections = true; - c.CreateProjection() - .ForMember(d => d.Bars, o => o.ExplicitExpansion()) - .ForMember(d => d.Bazs, o => o.ExplicitExpansion()); + c.CreateProjection() + .ForMember(d => d.Bars, o => o.ExplicitExpansion()) + .ForMember(d => d.Bazs, o => o.ExplicitExpansion()); - c.CreateProjection(); - c.CreateProjection(); - }); + c.CreateProjection(); + c.CreateProjection(); + }); - [Fact] - public void Should_work() + [Fact] + public void Should_work() + { + using(var context = new MyContext()) { - using(var context = new MyContext()) - { - var foos = ProjectTo(context.Foos.AsNoTracking(), null, m => m.Bars).ToList(); + var foos = ProjectTo(context.Foos.AsNoTracking(), null, m => m.Bars).ToList(); - foos[0].Bars.ShouldNotBeNull(); - foos[0].Bazs.ShouldBeNull(); - } + foos[0].Bars.ShouldNotBeNull(); + foos[0].Bazs.ShouldBeNull(); } } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/ExplicitExpansion/ProjectionWithExplicitExpansion.cs b/src/IntegrationTests/ExplicitExpansion/ProjectionWithExplicitExpansion.cs index 87ba3b7d67..b1f426a417 100644 --- a/src/IntegrationTests/ExplicitExpansion/ProjectionWithExplicitExpansion.cs +++ b/src/IntegrationTests/ExplicitExpansion/ProjectionWithExplicitExpansion.cs @@ -2,232 +2,235 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -using System.Data.Entity; using System.Linq; using System.Text.RegularExpressions; +using System.Threading.Tasks; +using AutoMapper.QueryableExtensions; +using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; using Shouldly; using Xunit; -namespace AutoMapper.IntegrationTests.ProjectionWithExplicitExpansionExtension +namespace AutoMapper.IntegrationTests.ExplicitExpansion; + +public static class Ext { - public static class Ext + public static void SqlShouldSelectColumn (this string sqlSelect, string columnName)=> sqlSelect.ShouldContain($".[{columnName}]"); + public static void SqlShouldNotSelectColumn(this string sqlSelect, string columnName)=> sqlSelect.ShouldNotContain($"[{columnName}]"); + public static void SqlFromShouldStartWith (this string sqlSelect, string tableName) { - public static void SqlShouldSelectColumn (this string sqlSelect, string columnName)=> sqlSelect.ShouldContain($".[{columnName}] AS [{columnName}]"); - public static void SqlShouldNotSelectColumn(this string sqlSelect, string columnName)=> sqlSelect.ShouldNotContain(columnName); - public static void SqlFromShouldStartWith (this string sqlSelect, string tableName) - { - Regex regex = new Regex($@"FROM(\s+)\[dbo\]\.\[{tableName}\](\s+)AS"); - regex.Match(sqlSelect).Success.ShouldBeTrue(); - // sqlSelect.ShouldContain($"FROM [dbo].[{tableName}] AS"); - } + Regex regex = new Regex($@"FROM(\s+)\[{tableName}\](\s+)AS"); + regex.Match(sqlSelect).Success.ShouldBeTrue(); + // sqlSelect.ShouldContain($"FROM [dbo].[{tableName}] AS"); } } -namespace AutoMapper.IntegrationTests -{ - using UnitTests; - using QueryableExtensions; - using ProjectionWithExplicitExpansionExtension; - using NameSourceType = String; using NameDtoType = String ; // Example of Reference Type - using DescSourceType = Int32 ; using DescDtoType = Nullable; // Example of Value Type mapped to appropriate Nullable +// Example of Value Type mapped to appropriate Nullable - public class ProjectionWithExplicitExpansion : AutoMapperSpecBase +public class ProjectionWithExplicitExpansion : AutoMapperSpecBase, IAsyncLifetime +{ + public class SourceDeepInner { - public class SourceDeepInner - { - [Key, DatabaseGenerated(DatabaseGeneratedOption.None)] - public DescSourceType Dide { get; set; } - public DescSourceType Did1 { get; set; } - } - public class SourceInner - { - [Key, DatabaseGenerated(DatabaseGeneratedOption.None)] - public DescSourceType Ides { get; set; } - public DescSourceType Ide1 { get; set; } - public SourceDeepInner Deep { get; set; } - } - public class Source - { [Key, DatabaseGenerated(DatabaseGeneratedOption.None)] - public DescSourceType Desc { get; set; } - public NameSourceType Name { get; set; } - public SourceInner Inner { get; set; } - } - public class Dto - { - public NameDtoType Name { get; set; } - public DescDtoType Desc { get; set; } - public DescDtoType InnerDescFlattened { get; set; } - public DescDtoType InnerFlattenedNonKey { get; set; } - public DescDtoType DeepFlattened { get; set; } - } + [Key, DatabaseGenerated(DatabaseGeneratedOption.None)] + public Int32 Dide { get; set; } + public Int32 Did1 { get; set; } + } + public class SourceInner + { + [Key, DatabaseGenerated(DatabaseGeneratedOption.None)] + public Int32 Ides { get; set; } + public Int32 Ide1 { get; set; } + public SourceDeepInner Deep { get; set; } + } + public class Source + { [Key, DatabaseGenerated(DatabaseGeneratedOption.None)] + public Int32 Desc { get; set; } + public String Name { get; set; } + public SourceInner Inner { get; set; } + } + public class Dto + { + public String Name { get; set; } + public Nullable Desc { get; set; } + public Nullable InnerDescFlattened { get; set; } + public Nullable InnerFlattenedNonKey { get; set; } + public Nullable DeepFlattened { get; set; } + } + + public class Context : LocalDbContext + { + public List Log = new List(); - public class Context : DbContext + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { - public List Log = new List(); - public Context() - { - Database.SetInitializer(new DatabaseInitializer()); - Database.Log += s => Log.Add(s); - } - - public DbSet Sources { get; set; } - public DbSet SourceInners { get; set; } - public DbSet SourceDeepInners { get; set; } - - public string GetLastSelectSqlLogEntry() => Log.Last(_ => _.TrimStart().StartsWith("SELECT")); + optionsBuilder.LogTo(s => Log.Add(s)); + base.OnConfiguring(optionsBuilder); } - private static readonly IQueryable _iq = new List { - new Source() { Name = "Name1", Desc = -12, Inner = new SourceInner { - Ides = -25, Ide1 = -7, - Deep = new SourceDeepInner() { Dide = 28, Did1 = 38,} } }, - } .AsQueryable(); + public DbSet Sources { get; set; } + public DbSet SourceInners { get; set; } + public DbSet SourceDeepInners { get; set; } + + public string GetLastSelectSqlLogEntry() => Log.LastOrDefault(_ => _.Contains("SELECT")); + } + + private static readonly IQueryable _iq = new List { + new Source() { Name = "Name1", Desc = -12, Inner = new SourceInner { + Ides = -25, Ide1 = -7, + Deep = new SourceDeepInner() { Dide = 28, Did1 = 38,} } }, + } .AsQueryable(); - private static readonly Source _iqf = _iq.First(); + private static readonly Source _iqf = _iq.First(); - public class DatabaseInitializer : CreateDatabaseIfNotExists + public class DatabaseInitializer : CreateDatabaseIfNotExists + { + protected override void Seed(Context context) { - protected override void Seed(Context context) - { - context.Sources.Add(_iqf); - base.Seed(context); - } + context.Sources.Add(_iqf); + base.Seed(context); } + } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection() - .ForMember(dto => dto.Desc, conf => conf.ExplicitExpansion()) - .ForMember(dto => dto.Name, conf => conf.ExplicitExpansion()) - .ForMember(dto => dto.InnerDescFlattened, conf => { conf.ExplicitExpansion(); conf.MapFrom(_ => _.Inner.Ides); }) - .ForMember(dto => dto.InnerFlattenedNonKey, conf => { conf.ExplicitExpansion(); conf.MapFrom(_ => _.Inner.Ide1); }) - .ForMember(dto => dto.DeepFlattened, conf => { conf.ExplicitExpansion(); conf.MapFrom(_ => _.Inner.Deep.Dide); }) - ;}); - - [Fact] - public void NoExplicitExpansion() + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection() + .ForMember(dto => dto.Desc, conf => conf.ExplicitExpansion()) + .ForMember(dto => dto.Name, conf => conf.ExplicitExpansion()) + .ForMember(dto => dto.InnerDescFlattened, conf => { conf.ExplicitExpansion(); conf.MapFrom(_ => _.Inner.Ides); }) + .ForMember(dto => dto.InnerFlattenedNonKey, conf => { conf.ExplicitExpansion(); conf.MapFrom(_ => _.Inner.Ide1); }) + .ForMember(dto => dto.DeepFlattened, conf => { conf.ExplicitExpansion(); conf.MapFrom(_ => _.Inner.Deep.Dide); }) + ;}); + + [Fact] + public void NoExplicitExpansion() + { + using (var ctx = new Context()) { - using (var ctx = new Context()) - { - var dto = ProjectTo(ctx.Sources).ToList().First(); - var sqlSelect = ctx.GetLastSelectSqlLogEntry(); - sqlSelect.SqlFromShouldStartWith(nameof(ctx.Sources)); - sqlSelect.ShouldNotContain("JOIN"); - sqlSelect.ShouldNotContain(nameof(ctx.SourceInners)); dto.InnerDescFlattened.ShouldBeNull(); - - sqlSelect.SqlShouldNotSelectColumn(nameof(_iqf.Name)); dto.Name.ShouldBeNull(); - sqlSelect.SqlShouldNotSelectColumn(nameof(_iqf.Desc)); dto.Desc.ShouldBeNull(); - } + var dto = ProjectTo(ctx.Sources).ToList().First(); + var sqlSelect = ctx.GetLastSelectSqlLogEntry(); + sqlSelect.SqlFromShouldStartWith(nameof(ctx.Sources)); + sqlSelect.ShouldNotContain("JOIN"); + sqlSelect.ShouldNotContain(nameof(ctx.SourceInners)); dto.InnerDescFlattened.ShouldBeNull(); + + sqlSelect.SqlShouldNotSelectColumn(nameof(_iqf.Name)); dto.Name.ShouldBeNull(); + sqlSelect.SqlShouldNotSelectColumn(nameof(_iqf.Desc)); dto.Desc.ShouldBeNull(); } + } - [Fact] - public void ProjectReferenceType() + [Fact] + public void ProjectReferenceType() + { + using (var ctx = new Context()) { - using (var ctx = new Context()) - { - var dto = ProjectTo(ctx.Sources, null, _ => _.Name).First(); - var sqlSelect = ctx.GetLastSelectSqlLogEntry(); - sqlSelect.SqlFromShouldStartWith(nameof(ctx.Sources)); - sqlSelect.ShouldNotContain("JOIN"); - sqlSelect.ShouldNotContain(nameof(ctx.SourceInners)); dto.InnerDescFlattened.ShouldBeNull(); - - dto.Name.ShouldBe(_iqf.Name); sqlSelect.SqlShouldSelectColumn (nameof(_iqf.Name)); - dto.Desc.ShouldBeNull() ; sqlSelect.SqlShouldNotSelectColumn(nameof(_iqf.Desc)); - } + var dto = ProjectTo(ctx.Sources, null, _ => _.Name).First(); + var sqlSelect = ctx.GetLastSelectSqlLogEntry(); + sqlSelect.SqlFromShouldStartWith(nameof(ctx.Sources)); + sqlSelect.ShouldNotContain("JOIN"); + sqlSelect.ShouldNotContain(nameof(ctx.SourceInners)); dto.InnerDescFlattened.ShouldBeNull(); + + dto.Name.ShouldBe(_iqf.Name); sqlSelect.SqlShouldSelectColumn (nameof(_iqf.Name)); + dto.Desc.ShouldBeNull() ; sqlSelect.SqlShouldNotSelectColumn(nameof(_iqf.Desc)); } - [Fact] - public void ProjectValueType() + } + [Fact] + public void ProjectValueType() + { + using (var ctx = new Context()) { - using (var ctx = new Context()) - { - var dto = ProjectTo(ctx.Sources, null, _ => _.Desc).First(); + var dto = ProjectTo(ctx.Sources, null, _ => _.Desc).First(); - var sqlSelect = ctx.GetLastSelectSqlLogEntry(); - sqlSelect.SqlFromShouldStartWith(nameof(ctx.Sources)); - sqlSelect.ShouldNotContain("JOIN"); - sqlSelect.ShouldNotContain(nameof(ctx.SourceInners)); dto.InnerDescFlattened.ShouldBeNull(); + var sqlSelect = ctx.GetLastSelectSqlLogEntry(); + sqlSelect.SqlFromShouldStartWith(nameof(ctx.Sources)); + sqlSelect.ShouldNotContain("JOIN"); + sqlSelect.ShouldNotContain(nameof(ctx.SourceInners)); dto.InnerDescFlattened.ShouldBeNull(); - dto.Desc.ShouldBe(_iqf.Desc); sqlSelect.ShouldContain (nameof(_iqf.Desc)); - dto.Name.ShouldBeNull() ; sqlSelect.ShouldNotContain(nameof(_iqf.Name)); + dto.Desc.ShouldBe(_iqf.Desc); sqlSelect.ShouldContain (nameof(_iqf.Desc)); + dto.Name.ShouldBeNull() ; sqlSelect.ShouldNotContain(nameof(_iqf.Name)); - } } - [Fact] - public void ProjectBoth() + } + [Fact] + public void ProjectBoth() + { + using (var ctx = new Context()) { - using (var ctx = new Context()) - { - var dto = ProjectTo(ctx.Sources, null, _ => _.Name, _ => _.Desc).First(); - - var sqlSelect = ctx.GetLastSelectSqlLogEntry(); - sqlSelect.SqlFromShouldStartWith(nameof(ctx.Sources)); - sqlSelect.ShouldNotContain("JOIN"); - sqlSelect.ShouldNotContain(nameof(ctx.SourceInners)); dto.InnerDescFlattened.ShouldBeNull(); - - sqlSelect.SqlShouldSelectColumn(nameof(_iqf.Name)); dto.Name.ShouldBe(_iqf.Name); - sqlSelect.SqlShouldSelectColumn(nameof(_iqf.Desc)); dto.Desc.ShouldBe(_iqf.Desc); - } + var dto = ProjectTo(ctx.Sources, null, _ => _.Name, _ => _.Desc).First(); + + var sqlSelect = ctx.GetLastSelectSqlLogEntry(); + sqlSelect.SqlFromShouldStartWith(nameof(ctx.Sources)); + sqlSelect.ShouldNotContain("JOIN"); + sqlSelect.ShouldNotContain(nameof(ctx.SourceInners)); dto.InnerDescFlattened.ShouldBeNull(); + + dto.Name.ShouldBe(_iqf.Name); + dto.Desc.ShouldBe(_iqf.Desc); } + } - [Fact] - public void ProjectInner() + [Fact] + public void ProjectInner() + { + using (var ctx = new Context()) { - using (var ctx = new Context()) - { - var dto = ProjectTo(ctx.Sources, null, _ => _.InnerDescFlattened).ToList().First(); - - dto.InnerDescFlattened.ShouldBe(_iqf.Inner.Ides); - dto.InnerFlattenedNonKey.ShouldBeNull(); - dto.DeepFlattened.ShouldBeNull(); - - var sqlSelect = ctx.GetLastSelectSqlLogEntry(); - sqlSelect.SqlFromShouldStartWith(nameof(ctx.Sources)); - sqlSelect.ShouldNotContain("JOIN"); // ??? - sqlSelect.ShouldNotContain(nameof(ctx.SourceInners)); // ??? - sqlSelect.SqlShouldNotSelectColumn(nameof(_iqf.Name)); dto.Name.ShouldBeNull(); - sqlSelect.SqlShouldNotSelectColumn(nameof(_iqf.Desc)); dto.Desc.ShouldBeNull(); - } + var dto = ProjectTo(ctx.Sources, null, _ => _.InnerDescFlattened).ToList().First(); + + dto.InnerDescFlattened.ShouldBe(_iqf.Inner.Ides); + dto.InnerFlattenedNonKey.ShouldBeNull(); + dto.DeepFlattened.ShouldBeNull(); + + var sqlSelect = ctx.GetLastSelectSqlLogEntry(); + sqlSelect.SqlFromShouldStartWith(nameof(ctx.Sources)); + sqlSelect.SqlShouldNotSelectColumn(nameof(_iqf.Name)); dto.Name.ShouldBeNull(); + sqlSelect.SqlShouldNotSelectColumn(nameof(_iqf.Desc)); dto.Desc.ShouldBeNull(); } + } - [Fact] - public void ProjectInnerNonKey() + [Fact] + public void ProjectInnerNonKey() + { + using (var ctx = new Context()) { - using (var ctx = new Context()) - { - var dto = ProjectTo(ctx.Sources, null, _ => _.InnerFlattenedNonKey).ToList().First(); - - dto.InnerFlattenedNonKey.ShouldBe(_iqf.Inner.Ide1); - dto.InnerDescFlattened.ShouldBeNull(); - dto.DeepFlattened.ShouldBeNull(); - - var sqlSelect = ctx.GetLastSelectSqlLogEntry(); - sqlSelect.SqlFromShouldStartWith(nameof(ctx.Sources)); - sqlSelect.ShouldContain("JOIN"); - sqlSelect.ShouldContain(nameof(ctx.SourceInners)); - sqlSelect.ShouldNotContain(nameof(ctx.SourceDeepInners)); - sqlSelect.SqlShouldNotSelectColumn(nameof(_iqf.Name)); dto.Name.ShouldBeNull(); - sqlSelect.SqlShouldNotSelectColumn(nameof(_iqf.Desc)); dto.Desc.ShouldBeNull(); - } + var dto = ProjectTo(ctx.Sources, null, _ => _.InnerFlattenedNonKey).ToList().First(); + + dto.InnerFlattenedNonKey.ShouldBe(_iqf.Inner.Ide1); + dto.InnerDescFlattened.ShouldBeNull(); + dto.DeepFlattened.ShouldBeNull(); + + var sqlSelect = ctx.GetLastSelectSqlLogEntry(); + sqlSelect.SqlFromShouldStartWith(nameof(ctx.Sources)); + sqlSelect.ShouldContain("JOIN"); + sqlSelect.ShouldContain(nameof(ctx.SourceInners)); + sqlSelect.ShouldNotContain(nameof(ctx.SourceDeepInners)); + sqlSelect.SqlShouldNotSelectColumn(nameof(_iqf.Name)); dto.Name.ShouldBeNull(); + sqlSelect.SqlShouldNotSelectColumn(nameof(_iqf.Desc)); dto.Desc.ShouldBeNull(); } + } - [Fact] - public void ProjectDeepInner() + [Fact] + public void ProjectDeepInner() + { + using (var ctx = new Context()) { - using (var ctx = new Context()) - { - var dto = ProjectTo(ctx.Sources, null, _ => _.DeepFlattened).ToList().First(); - var sqlSelect = ctx.GetLastSelectSqlLogEntry(); - sqlSelect.SqlFromShouldStartWith(nameof(ctx.Sources)); - - dto.DeepFlattened.ShouldBe(_iqf.Inner.Deep.Dide); - dto.InnerDescFlattened.ShouldBeNull(); - - sqlSelect.ShouldContain("JOIN"); - sqlSelect.ShouldContain(nameof(ctx.SourceInners)); - sqlSelect.ShouldContain("JOIN"); // ??? - sqlSelect.SqlShouldNotSelectColumn(nameof(_iqf.Name)); dto.Name.ShouldBeNull(); - sqlSelect.SqlShouldNotSelectColumn(nameof(_iqf.Desc)); dto.Desc.ShouldBeNull(); - } + var dto = ProjectTo(ctx.Sources, null, _ => _.DeepFlattened).ToList().First(); + var sqlSelect = ctx.GetLastSelectSqlLogEntry(); + sqlSelect.SqlFromShouldStartWith(nameof(ctx.Sources)); + + dto.DeepFlattened.ShouldBe(_iqf.Inner.Deep.Dide); + dto.InnerDescFlattened.ShouldBeNull(); + + sqlSelect.ShouldContain("JOIN"); + sqlSelect.ShouldContain(nameof(ctx.SourceInners)); + sqlSelect.ShouldContain("JOIN"); // ??? + sqlSelect.SqlShouldNotSelectColumn(nameof(_iqf.Name)); dto.Name.ShouldBeNull(); + sqlSelect.SqlShouldNotSelectColumn(nameof(_iqf.Desc)); dto.Desc.ShouldBeNull(); } } -} + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; +} \ No newline at end of file diff --git a/src/IntegrationTests/ICollectionAggregateProjections.cs b/src/IntegrationTests/ICollectionAggregateProjections.cs index 9703129284..6601332c63 100644 --- a/src/IntegrationTests/ICollectionAggregateProjections.cs +++ b/src/IntegrationTests/ICollectionAggregateProjections.cs @@ -1,88 +1,93 @@ using System.ComponentModel.DataAnnotations; -using System.Data.Entity; +using Microsoft.EntityFrameworkCore; using System.Linq; +using System.Threading.Tasks; using Shouldly; using Xunit; -namespace AutoMapper.IntegrationTests +namespace AutoMapper.IntegrationTests; + +using UnitTests; +using QueryableExtensions; +using System.Collections.Generic; + +public class ICollectionAggregateProjections : AutoMapperSpecBase, IAsyncLifetime { - using UnitTests; - using QueryableExtensions; - using System.Collections.Generic; + public class Customer + { + [Key] + public int Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + public ICollection Items { get; set; } + } - public class ICollectionAggregateProjections : AutoMapperSpecBase + public class Item { - public class Customer - { - [Key] - public int Id { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - public ICollection Items { get; set; } - } + public int Id { get; set; } + public int Code { get; set; } + } - public class Item - { - public int Id { get; set; } - public int Code { get; set; } - } + public class CustomerViewModel + { + public int ItemCodesCount { get; set; } + public int ItemCodesMin { get; set; } + public int ItemCodesMax { get; set; } + public int ItemCodesSum { get; set; } + } - public class CustomerViewModel - { - public int ItemCodesCount { get; set; } - public int ItemCodesMin { get; set; } - public int ItemCodesMax { get; set; } - public int ItemCodesSum { get; set; } - } + public class Context : LocalDbContext + { + public DbSet Customers { get; set; } + } - public class Context : DbContext + public class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(Context context) { - public Context() + context.Customers.Add(new Customer { - Database.SetInitializer(new DatabaseInitializer()); - } + FirstName = "Bob", + LastName = "Smith", + Items = new[] { new Item { Code = 1 }, new Item { Code = 3 }, new Item { Code = 5 } } + }); - public DbSet Customers { get; set; } + base.Seed(context); } + } + + public class CustomerItemCodes + { + public List ItemCodes { get; set; } + } - public class DatabaseInitializer : DropCreateDatabaseAlways + protected override MapperConfiguration CreateConfiguration() => new(cfg => cfg.CreateProjection()); + + [Fact] + public void Can_map_with_projection() + { + using (var context = new Context()) { - protected override void Seed(Context context) + var result = ProjectTo(context.Customers.Select(customer => new CustomerItemCodes { - context.Customers.Add(new Customer - { - Id = 1, - FirstName = "Bob", - LastName = "Smith", - Items = new[] { new Item { Code = 1 }, new Item { Code = 3 }, new Item { Code = 5 } } - }); - - base.Seed(context); - } - } + ItemCodes = customer.Items.Select(item => item.Code).ToList() + })).Single(); - public class CustomerItemCodes - { - public List ItemCodes { get; set; } + result.ItemCodesCount.ShouldBe(3); + result.ItemCodesMin.ShouldBe(1); + result.ItemCodesMax.ShouldBe(5); + result.ItemCodesSum.ShouldBe(9); } + } - protected override MapperConfiguration CreateConfiguration() => new(cfg => cfg.CreateProjection()); - [Fact] - public void Can_map_with_projection() - { - using (var context = new Context()) - { - var result = ProjectTo(context.Customers.Select(customer => new CustomerItemCodes - { - ItemCodes = customer.Items.Select(item => item.Code).ToList() - })).Single(); - - result.ItemCodesCount.ShouldBe(3); - result.ItemCodesMin.ShouldBe(1); - result.ItemCodesMax.ShouldBe(5); - result.ItemCodesSum.ShouldBe(9); - } - } + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); } -} + + public Task DisposeAsync() => Task.CompletedTask; + +} \ No newline at end of file diff --git a/src/IntegrationTests/IEnumerableAggregateProjections.cs b/src/IntegrationTests/IEnumerableAggregateProjections.cs index b8062848ca..fcaa46180e 100644 --- a/src/IntegrationTests/IEnumerableAggregateProjections.cs +++ b/src/IntegrationTests/IEnumerableAggregateProjections.cs @@ -1,88 +1,93 @@ using System.ComponentModel.DataAnnotations; -using System.Data.Entity; +using Microsoft.EntityFrameworkCore; using System.Linq; +using System.Threading.Tasks; using Shouldly; using Xunit; -namespace AutoMapper.IntegrationTests +namespace AutoMapper.IntegrationTests; + +using UnitTests; +using QueryableExtensions; +using System.Collections.Generic; + +public class IEnumerableAggregateProjections : AutoMapperSpecBase, IAsyncLifetime { - using UnitTests; - using QueryableExtensions; - using System.Collections.Generic; + public class Customer + { + [Key] + public int Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + public ICollection Items { get; set; } + } - public class IEnumerableAggregateProjections : AutoMapperSpecBase + public class Item { - public class Customer - { - [Key] - public int Id { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - public ICollection Items { get; set; } - } + public int Id { get; set; } + public int Code { get; set; } + } - public class Item - { - public int Id { get; set; } - public int Code { get; set; } - } + public class CustomerViewModel + { + public int ItemCodesCount { get; set; } + public int ItemCodesMin { get; set; } + public int ItemCodesMax { get; set; } + public int ItemCodesSum { get; set; } + } - public class CustomerViewModel - { - public int ItemCodesCount { get; set; } - public int ItemCodesMin { get; set; } - public int ItemCodesMax { get; set; } - public int ItemCodesSum { get; set; } - } + public class Context : LocalDbContext + { + public DbSet Customers { get; set; } + } - public class Context : DbContext + public class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(Context context) { - public Context() + context.Customers.Add(new Customer { - Database.SetInitializer(new DatabaseInitializer()); - } + FirstName = "Bob", + LastName = "Smith", + Items = new[] { new Item { Code = 1 }, new Item { Code = 3 }, new Item { Code = 5 } } + }); - public DbSet Customers { get; set; } + base.Seed(context); } + } + + public class CustomerItemCodes + { + public IEnumerable ItemCodes { get; set; } + } - public class DatabaseInitializer : DropCreateDatabaseAlways + protected override MapperConfiguration CreateConfiguration() => new(cfg => cfg.CreateProjection()); + + [Fact] + public void Can_map_with_projection() + { + using (var context = new Context()) { - protected override void Seed(Context context) + var result = ProjectTo(context.Customers.Select(customer => new CustomerItemCodes { - context.Customers.Add(new Customer - { - Id = 1, - FirstName = "Bob", - LastName = "Smith", - Items = new[] { new Item { Code = 1 }, new Item { Code = 3 }, new Item { Code = 5 } } - }); - - base.Seed(context); - } - } + ItemCodes = customer.Items.Select(item => item.Code) + })).Single(); - public class CustomerItemCodes - { - public IEnumerable ItemCodes { get; set; } + result.ItemCodesCount.ShouldBe(3); + result.ItemCodesMin.ShouldBe(1); + result.ItemCodesMax.ShouldBe(5); + result.ItemCodesSum.ShouldBe(9); } + } - protected override MapperConfiguration CreateConfiguration() => new(cfg => cfg.CreateProjection()); - [Fact] - public void Can_map_with_projection() - { - using (var context = new Context()) - { - var result = ProjectTo(context.Customers.Select(customer => new CustomerItemCodes - { - ItemCodes = customer.Items.Select(item => item.Code) - })).Single(); - - result.ItemCodesCount.ShouldBe(3); - result.ItemCodesMin.ShouldBe(1); - result.ItemCodesMax.ShouldBe(5); - result.ItemCodesSum.ShouldBe(9); - } - } + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); } -} + + public Task DisposeAsync() => Task.CompletedTask; + +} \ No newline at end of file diff --git a/src/IntegrationTests/IEnumerableMemberProjections.cs b/src/IntegrationTests/IEnumerableMemberProjections.cs index 6d916a2a09..3ecd5c0ea9 100644 --- a/src/IntegrationTests/IEnumerableMemberProjections.cs +++ b/src/IntegrationTests/IEnumerableMemberProjections.cs @@ -1,89 +1,93 @@ using System.ComponentModel.DataAnnotations; -using System.Data.Entity; +using Microsoft.EntityFrameworkCore; using System.Linq; +using System.Threading.Tasks; using Shouldly; using Xunit; -namespace AutoMapper.IntegrationTests +namespace AutoMapper.IntegrationTests; + +using UnitTests; +using QueryableExtensions; +using System.Collections.Generic; + +public class IEnumerableMemberProjections : AutoMapperSpecBase, IAsyncLifetime { - using UnitTests; - using QueryableExtensions; - using System.Collections.Generic; + public class Customer + { + [Key] + public int Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + public ICollection Items { get; set; } + } - public class IEnumerableMemberProjections : AutoMapperSpecBase + public class Item { - public class Customer - { - [Key] - public int Id { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - public ICollection Items { get; set; } - } + public int Id { get; set; } + public int Code { get; set; } + } - public class Item - { - public int Id { get; set; } - public int Code { get; set; } - } + public class ItemModel + { + public int Id { get; set; } + public int Code { get; set; } + } - public class ItemModel - { - public int Id { get; set; } - public int Code { get; set; } - } + public class CustomerViewModel + { + public IEnumerable Items { get; set; } + } - public class CustomerViewModel - { - public IEnumerable Items { get; set; } - } + public class Context : LocalDbContext + { + public DbSet Customers { get; set; } + } - public class Context : DbContext + public class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(Context context) { - public Context() + context.Customers.Add(new Customer { - Database.SetInitializer(new DatabaseInitializer()); - } - - public DbSet Customers { get; set; } - } + FirstName = "Bob", + LastName = "Smith", + Items = new[] { new Item { Code = 1 }, new Item { Code = 3 }, new Item { Code = 5 } } + }); - public class DatabaseInitializer : DropCreateDatabaseAlways - { - protected override void Seed(Context context) - { - context.Customers.Add(new Customer - { - Id = 1, - FirstName = "Bob", - LastName = "Smith", - Items = new[] { new Item { Code = 1 }, new Item { Code = 3 }, new Item { Code = 5 } } - }); - - base.Seed(context); - } + base.Seed(context); } + } - public class CustomerItemCodes - { - public IEnumerable ItemCodes { get; set; } - } + public class CustomerItemCodes + { + public IEnumerable ItemCodes { get; set; } + } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection(); - cfg.CreateProjection(); - }); + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection(); + cfg.CreateProjection(); + }); - [Fact] - public void Can_map_to_ienumerable() + [Fact] + public void Can_map_to_ienumerable() + { + using (var context = new Context()) { - using (var context = new Context()) - { - var result = ProjectTo(context.Customers).Single(); + var result = ProjectTo(context.Customers).Single(); - result.Items.Count().ShouldBe(3); - } + result.Items.Count().ShouldBe(3); } } -} + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; + +} \ No newline at end of file diff --git a/src/IntegrationTests/IncludeMembers.cs b/src/IntegrationTests/IncludeMembers.cs index dd2fb81e78..60ee7274d7 100644 --- a/src/IntegrationTests/IncludeMembers.cs +++ b/src/IntegrationTests/IncludeMembers.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using System.Data.Entity; +using Microsoft.EntityFrameworkCore; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -8,1076 +8,1131 @@ using Shouldly; using Xunit; -namespace AutoMapper.IntegrationTests +namespace AutoMapper.IntegrationTests; + +public class IncludeMembers : AutoMapperSpecBase, IAsyncLifetime { - public class IncludeMembers : AutoMapperSpecBase + class Source { - class Source - { - public int Id { get; set; } - public string Name { get; set; } - public InnerSource InnerSource { get; set; } - public OtherInnerSource OtherInnerSource { get; set; } - } - class InnerSource - { - public int Id { get; set; } - public string Name { get; set; } - public string Description { get; set; } - } - class OtherInnerSource - { - public int Id { get; set; } - public string Name { get; set; } - public string Description { get; set; } - public string Title { get; set; } - } - class Destination - { - public int Id { get; set; } - public string Name { get; set; } - public string Description { get; set; } - public string Title { get; set; } - } - class Context : DbContext - { - public Context() - { - Database.SetInitializer(new DatabaseInitializer()); - } - - public DbSet Sources { get; set; } - } + public int Id { get; set; } + public string Name { get; set; } + public InnerSource InnerSource { get; set; } + public OtherInnerSource OtherInnerSource { get; set; } + } + class InnerSource + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + } + class OtherInnerSource + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public string Title { get; set; } + } + class Destination + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public string Title { get; set; } + } + class Context : LocalDbContext + { + public DbSet Sources { get; set; } + } - class DatabaseInitializer : DropCreateDatabaseAlways + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(Context context) { - protected override void Seed(Context context) - { - var source = new Source { Name = "name", InnerSource = new InnerSource { Description = "description" }, OtherInnerSource = new OtherInnerSource { Title = "title" } }; - context.Sources.Add(source); - base.Seed(context); - } + var source = new Source { Name = "name", InnerSource = new InnerSource { Description = "description" }, OtherInnerSource = new OtherInnerSource { Title = "title" } }; + context.Sources.Add(source); + base.Seed(context); } + } - protected override MapperConfiguration CreateConfiguration() => new(cfg=> - { - cfg.CreateProjection().IncludeMembers(s=>s.InnerSource, s=>s.OtherInnerSource); - cfg.CreateProjection(MemberList.None); - cfg.CreateProjection(MemberList.None); - }); - [Fact] - public void Should_flatten() + protected override MapperConfiguration CreateConfiguration() => new(cfg=> + { + cfg.CreateProjection().IncludeMembers(s=>s.InnerSource, s=>s.OtherInnerSource); + cfg.CreateProjection(MemberList.None); + cfg.CreateProjection(MemberList.None); + }); + [Fact] + public void Should_flatten() + { + using(var context = new Context()) { - using(var context = new Context()) - { - var projectTo = ProjectTo(context.Sources); - var result = projectTo.Single(); - result.Name.ShouldBe("name"); - result.Description.ShouldBe("description"); - result.Title.ShouldBe("title"); - } + var projectTo = ProjectTo(context.Sources); + var result = projectTo.Single(); + result.Name.ShouldBe("name"); + result.Description.ShouldBe("description"); + result.Title.ShouldBe("title"); } } - public class IncludeMembersExplicitExpansion : AutoMapperSpecBase + + public async Task InitializeAsync() { - class Source - { - public int Id { get; set; } - public string Name { get; set; } - public InnerSource InnerSource { get; set; } - public OtherInnerSource OtherInnerSource { get; set; } - } - class InnerSource - { - public int Id { get; set; } - public string Name { get; set; } - public string Description { get; set; } - } - class OtherInnerSource - { - public int Id { get; set; } - public string Name { get; set; } - public string Description { get; set; } - public string Title { get; set; } - } - class Destination - { - public int Id { get; set; } - public string Name { get; set; } - public string Description { get; set; } - public string Title { get; set; } - } - class Context : DbContext - { - public Context() - { - Database.SetInitializer(new DatabaseInitializer()); - } + var initializer = new DatabaseInitializer(); - public DbSet Sources { get; set; } - } + await initializer.Migrate(); + } - class DatabaseInitializer : DropCreateDatabaseAlways - { - protected override void Seed(Context context) - { - var source = new Source { Name = "name", InnerSource = new InnerSource { Description = "description" }, OtherInnerSource = new OtherInnerSource { Title = "title" } }; - context.Sources.Add(source); - base.Seed(context); - } - } + public Task DisposeAsync() => Task.CompletedTask; - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection().IncludeMembers(s => s.InnerSource, s => s.OtherInnerSource); - cfg.CreateProjection(MemberList.None).ForMember(d=>d.Description, o=>o.ExplicitExpansion()); - cfg.CreateProjection(MemberList.None).ForMember(d=>d.Title, o=>o.ExplicitExpansion()); - }); - [Fact] - public void Should_flatten() - { - using (var context = new Context()) - { - var projectTo = ProjectTo(context.Sources, null, d=>d.Title); - var result = projectTo.Single(); - result.Name.ShouldBe("name"); - result.Description.ShouldBeNull(); - result.Title.ShouldBe("title"); - } - } +} +public class IncludeMembersExplicitExpansion : AutoMapperSpecBase, IAsyncLifetime +{ + class Source + { + public int Id { get; set; } + public string Name { get; set; } + public InnerSource InnerSource { get; set; } + public OtherInnerSource OtherInnerSource { get; set; } + } + class InnerSource + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + } + class OtherInnerSource + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public string Title { get; set; } + } + class Destination + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public string Title { get; set; } + } + class Context : LocalDbContext + { + public DbSet Sources { get; set; } } - public class IncludeMembersFirstOrDefault : AutoMapperSpecBase + class DatabaseInitializer : DropCreateDatabaseAlways { - class Source - { - public int Id { get; set; } - public string Name { get; set; } - public List InnerSources { get; set; } = new List(); - public List OtherInnerSources { get; set; } = new List(); - } - class InnerSource - { - public int Id { get; set; } - public string Name { get; set; } - public string Description { get; set; } - public string Publisher { get; set; } - } - class OtherInnerSource + protected override void Seed(Context context) { - public int Id { get; set; } - public string Name { get; set; } - public string Description { get; set; } - public string Title { get; set; } - public string Author { get; set; } + var source = new Source { Name = "name", InnerSource = new InnerSource { Description = "description" }, OtherInnerSource = new OtherInnerSource { Title = "title" } }; + context.Sources.Add(source); + base.Seed(context); } - class Destination + } + + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection().IncludeMembers(s => s.InnerSource, s => s.OtherInnerSource); + cfg.CreateProjection(MemberList.None).ForMember(d=>d.Description, o=>o.ExplicitExpansion()); + cfg.CreateProjection(MemberList.None).ForMember(d=>d.Title, o=>o.ExplicitExpansion()); + }); + [Fact] + public void Should_flatten() + { + using (var context = new Context()) { - public int Id { get; set; } - public string Name { get; set; } - public string Description { get; set; } - public string Title { get; set; } - public string Author { get; set; } - public string Publisher { get; set; } + var projectTo = ProjectTo(context.Sources, null, d=>d.Title); + var result = projectTo.Single(); + result.Name.ShouldBe("name"); + result.Description.ShouldBeNull(); + result.Title.ShouldBe("title"); } - class Context : DbContext - { - public Context() - { - Database.SetInitializer(new DatabaseInitializer()); - } + } - public DbSet Sources { get; set; } - } - class DatabaseInitializer : DropCreateDatabaseAlways + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; + +} + +public class IncludeMembersFirstOrDefault : AutoMapperSpecBase, IAsyncLifetime +{ + class Source + { + public int Id { get; set; } + public string Name { get; set; } + public List InnerSources { get; set; } = new List(); + public List OtherInnerSources { get; set; } = new List(); + } + class InnerSource + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public string Publisher { get; set; } + } + class OtherInnerSource + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public string Title { get; set; } + public string Author { get; set; } + } + class Destination + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public string Title { get; set; } + public string Author { get; set; } + public string Publisher { get; set; } + } + class Context : LocalDbContext + { + public DbSet Sources { get; set; } + } + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(Context context) { - protected override void Seed(Context context) + var source = new Source { - var source = new Source - { - Name = "name", - InnerSources = { new InnerSource { Description = "description", Publisher = "publisher" } }, - OtherInnerSources = { new OtherInnerSource { Title = "title", Author = "author" } } - }; - context.Sources.Add(source); - base.Seed(context); - } + Name = "name", + InnerSources = { new InnerSource { Description = "description", Publisher = "publisher" } }, + OtherInnerSources = { new OtherInnerSource { Title = "title", Author = "author" } } + }; + context.Sources.Add(source); + base.Seed(context); } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection().IncludeMembers(s => s.InnerSources.FirstOrDefault(), s => s.OtherInnerSources.FirstOrDefault()); - cfg.CreateProjection(MemberList.None); - cfg.CreateProjection(MemberList.None); - }); - [Fact] - public void Should_flatten() + } + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection().IncludeMembers(s => s.InnerSources.FirstOrDefault(), s => s.OtherInnerSources.FirstOrDefault()); + cfg.CreateProjection(MemberList.None); + cfg.CreateProjection(MemberList.None); + }); + [Fact] + public void Should_flatten() + { + using (var context = new Context()) { - using (var context = new Context()) - { - var projectTo = ProjectTo(context.Sources); - FirstOrDefaultCounter.Assert(projectTo, 2); - var result = projectTo.Single(); - result.Name.ShouldBe("name"); - result.Description.ShouldBe("description"); - result.Title.ShouldBe("title"); - result.Author.ShouldBe("author"); - result.Publisher.ShouldBe("publisher"); - } + var projectTo = ProjectTo(context.Sources); + FirstOrDefaultCounter.Assert(projectTo, 2); + var result = projectTo.Single(); + result.Name.ShouldBe("name"); + result.Description.ShouldBe("description"); + result.Title.ShouldBe("title"); + result.Author.ShouldBe("author"); + result.Publisher.ShouldBe("publisher"); } } - public class IncludeMembersFirstOrDefaultWithMapFromExpression : AutoMapperSpecBase + public async Task InitializeAsync() { - class Source - { - public int Id { get; set; } - public string Name { get; set; } - public List InnerSources { get; set; } = new List(); - public List OtherInnerSources { get; set; } = new List(); - } - class InnerSource - { - public int Id { get; set; } - public string Name { get; set; } - public string Description1 { get; set; } - public string Publisher { get; set; } - } - class OtherInnerSource - { - public int Id { get; set; } - public string Name { get; set; } - public string Description { get; set; } - public string Title1 { get; set; } - public string Author { get; set; } - } - class Destination - { - public int Id { get; set; } - public string Name { get; set; } - public string Description { get; set; } - public string Title { get; set; } - public string Author { get; set; } - public string Publisher { get; set; } - } - class Context : DbContext - { - public Context() - { - Database.SetInitializer(new DatabaseInitializer()); - } + var initializer = new DatabaseInitializer(); - public DbSet Sources { get; set; } - } - class DatabaseInitializer : DropCreateDatabaseAlways - { - protected override void Seed(Context context) - { - var source = new Source - { - Name = "name", - InnerSources = { new InnerSource { Description1 = "description", Publisher = "publisher" } }, - OtherInnerSources = { new OtherInnerSource { Title1 = "title", Author = "author" } } - }; - context.Sources.Add(source); - base.Seed(context); - } - } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection().IncludeMembers(s => s.InnerSources.FirstOrDefault(), s => s.OtherInnerSources.FirstOrDefault()); - cfg.CreateProjection(MemberList.None).ForMember(d => d.Description, o => o.MapFrom(s => s.Description1)); - cfg.CreateProjection(MemberList.None).ForMember(d => d.Title, o => o.MapFrom(s => s.Title1)); - }); - [Fact] - public void Should_flatten() + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; + +} + +public class IncludeMembersFirstOrDefaultWithMapFromExpression : AutoMapperSpecBase, IAsyncLifetime +{ + class Source + { + public int Id { get; set; } + public string Name { get; set; } + public List InnerSources { get; set; } = new List(); + public List OtherInnerSources { get; set; } = new List(); + } + class InnerSource + { + public int Id { get; set; } + public string Name { get; set; } + public string Description1 { get; set; } + public string Publisher { get; set; } + } + class OtherInnerSource + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public string Title1 { get; set; } + public string Author { get; set; } + } + class Destination + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public string Title { get; set; } + public string Author { get; set; } + public string Publisher { get; set; } + } + class Context : LocalDbContext + { + public DbSet Sources { get; set; } + } + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(Context context) { - using (var context = new Context()) + var source = new Source { - var projectTo = ProjectTo(context.Sources); - FirstOrDefaultCounter.Assert(projectTo, 2); - var result = projectTo.Single(); - result.Name.ShouldBe("name"); - result.Description.ShouldBe("description"); - result.Title.ShouldBe("title"); - result.Author.ShouldBe("author"); - result.Publisher.ShouldBe("publisher"); - } + Name = "name", + InnerSources = { new InnerSource { Description1 = "description", Publisher = "publisher" } }, + OtherInnerSources = { new OtherInnerSource { Title1 = "title", Author = "author" } } + }; + context.Sources.Add(source); + base.Seed(context); } } - public class IncludeMembersFirstOrDefaultWithSubqueryMapFrom : AutoMapperSpecBase + protected override MapperConfiguration CreateConfiguration() => new(cfg => { - class Source - { - public int Id { get; set; } - public string Name { get; set; } - public List InnerSources { get; set; } = new List(); - public List OtherInnerSources { get; set; } = new List(); - } - class InnerSource - { - public int Id { get; set; } - public string Name { get; set; } - public List InnerSourceDetails { get; } = new List(); - } - class InnerSourceDetails - { - public int Id { get; set; } - public string Description { get; set; } - public string Publisher { get; set; } - } - class OtherInnerSource - { - public int Id { get; set; } - public string Name { get; set; } - public string Description { get; set; } - public List OtherInnerSourceDetails { get; } = new List(); - } - class OtherInnerSourceDetails - { - public int Id { get; set; } - public string Title { get; set; } - public string Author { get; set; } - } - class Destination - { - public int Id { get; set; } - public string Name { get; set; } - public DestinationDetails Details { get; set; } - public OtherDestinationDetails OtherDetails { get; set; } - } - class DestinationDetails - { - public string Description { get; set; } - public string Publisher { get; set; } - } - class OtherDestinationDetails + cfg.CreateProjection().IncludeMembers(s => s.InnerSources.FirstOrDefault(), s => s.OtherInnerSources.FirstOrDefault()); + cfg.CreateProjection(MemberList.None).ForMember(d => d.Description, o => o.MapFrom(s => s.Description1)); + cfg.CreateProjection(MemberList.None).ForMember(d => d.Title, o => o.MapFrom(s => s.Title1)); + }); + [Fact] + public void Should_flatten() + { + using (var context = new Context()) { - public string Title { get; set; } - public string Author { get; set; } + var projectTo = ProjectTo(context.Sources); + FirstOrDefaultCounter.Assert(projectTo, 2); + var result = projectTo.Single(); + result.Name.ShouldBe("name"); + result.Description.ShouldBe("description"); + result.Title.ShouldBe("title"); + result.Author.ShouldBe("author"); + result.Publisher.ShouldBe("publisher"); } - class Context : DbContext - { - public Context() - { - Database.SetInitializer(new DatabaseInitializer()); - } + } - public DbSet Sources { get; set; } - } - class DatabaseInitializer : DropCreateDatabaseAlways - { - protected override void Seed(Context context) - { - var source = new Source - { - Name = "name", - InnerSources = { new InnerSource { InnerSourceDetails = { new InnerSourceDetails { Description = "description", Publisher = "publisher" } } } }, - OtherInnerSources = { new OtherInnerSource { OtherInnerSourceDetails = { new OtherInnerSourceDetails { Title = "title", Author = "author" } } } } - }; - context.Sources.Add(source); - base.Seed(context); - } - } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection().IncludeMembers(s => s.InnerSources.FirstOrDefault(), s => s.OtherInnerSources.FirstOrDefault()); - cfg.CreateProjection(MemberList.None).ForMember(d => d.Details, o => o.MapFrom(s => s.InnerSourceDetails.FirstOrDefault())); - cfg.CreateProjection(MemberList.None).ForMember(d => d.OtherDetails, o => o.MapFrom(s => s.OtherInnerSourceDetails.FirstOrDefault())); - cfg.CreateProjection(); - cfg.CreateProjection(); - }); - [Fact] - public void Should_flatten() + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; +} +public class IncludeMembersFirstOrDefaultWithSubqueryMapFrom : AutoMapperSpecBase, IAsyncLifetime +{ + class Source + { + public int Id { get; set; } + public string Name { get; set; } + public List InnerSources { get; set; } = new List(); + public List OtherInnerSources { get; set; } = new List(); + } + class InnerSource + { + public int Id { get; set; } + public string Name { get; set; } + public List InnerSourceDetails { get; } = new List(); + } + class InnerSourceDetails + { + public int Id { get; set; } + public string Description { get; set; } + public string Publisher { get; set; } + } + class OtherInnerSource + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public List OtherInnerSourceDetails { get; } = new List(); + } + class OtherInnerSourceDetails + { + public int Id { get; set; } + public string Title { get; set; } + public string Author { get; set; } + } + class Destination + { + public int Id { get; set; } + public string Name { get; set; } + public DestinationDetails Details { get; set; } + public OtherDestinationDetails OtherDetails { get; set; } + } + class DestinationDetails + { + public string Description { get; set; } + public string Publisher { get; set; } + } + class OtherDestinationDetails + { + public string Title { get; set; } + public string Author { get; set; } + } + class Context : LocalDbContext + { + public DbSet Sources { get; set; } + } + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(Context context) { - using (var context = new Context()) + var source = new Source { - var projectTo = ProjectTo(context.Sources); - FirstOrDefaultCounter.Assert(projectTo, 4); - var result = projectTo.Single(); - result.Name.ShouldBe("name"); - result.Details.Description.ShouldBe("description"); - result.Details.Publisher.ShouldBe("publisher"); - result.OtherDetails.Title.ShouldBe("title"); - result.OtherDetails.Author.ShouldBe("author"); - } + Name = "name", + InnerSources = { new InnerSource { InnerSourceDetails = { new InnerSourceDetails { Description = "description", Publisher = "publisher" } } } }, + OtherInnerSources = { new OtherInnerSource { OtherInnerSourceDetails = { new OtherInnerSourceDetails { Title = "title", Author = "author" } } } } + }; + context.Sources.Add(source); + base.Seed(context); } } - public class IncludeMembersSelectFirstOrDefaultWithSubqueryMapFrom : AutoMapperSpecBase + protected override MapperConfiguration CreateConfiguration() => new(cfg => { - class Source - { - public int Id { get; set; } - public string Name { get; set; } - public List InnerSourceWrappers { get; set; } = new List(); - public List OtherInnerSources { get; set; } = new List(); - } - class InnerSourceWrapper - { - public int Id { get; set; } - public InnerSource InnerSource { get; set; } - } - class InnerSource - { - public int Id { get; set; } - public string Name { get; set; } - public List InnerSourceDetailsWrapper { get; } = new List(); - } - class InnerSourceDetailsWrapper - { - public int Id { get; set; } - public InnerSourceDetails InnerSourceDetails { get; set; } - } - class InnerSourceDetails - { - public int Id { get; set; } - public string Description { get; set; } - public string Publisher { get; set; } - } - class OtherInnerSource - { - public int Id { get; set; } - public string Name { get; set; } - public string Description { get; set; } - public List OtherInnerSourceDetails { get; } = new List(); - } - class OtherInnerSourceDetails - { - public int Id { get; set; } - public string Title { get; set; } - public string Author { get; set; } - } - class Destination - { - public int Id { get; set; } - public string Name { get; set; } - public DestinationDetails Details { get; set; } - public OtherDestinationDetails OtherDetails { get; set; } - } - class DestinationDetails - { - public string Description { get; set; } - public string Publisher { get; set; } - } - class OtherDestinationDetails + cfg.CreateProjection().IncludeMembers(s => s.InnerSources.FirstOrDefault(), s => s.OtherInnerSources.FirstOrDefault()); + cfg.CreateProjection(MemberList.None).ForMember(d => d.Details, o => o.MapFrom(s => s.InnerSourceDetails.FirstOrDefault())); + cfg.CreateProjection(MemberList.None).ForMember(d => d.OtherDetails, o => o.MapFrom(s => s.OtherInnerSourceDetails.FirstOrDefault())); + cfg.CreateProjection(); + cfg.CreateProjection(); + }); + [Fact] + public void Should_flatten() + { + using (var context = new Context()) { - public string Title { get; set; } - public string Author { get; set; } + var projectTo = ProjectTo(context.Sources); + FirstOrDefaultCounter.Assert(projectTo, 4); + var result = projectTo.Single(); + result.Name.ShouldBe("name"); + result.Details.Description.ShouldBe("description"); + result.Details.Publisher.ShouldBe("publisher"); + result.OtherDetails.Title.ShouldBe("title"); + result.OtherDetails.Author.ShouldBe("author"); } - class Context : DbContext - { - public Context() - { - Database.SetInitializer(new DatabaseInitializer()); - } + } - public DbSet Sources { get; set; } - } - class DatabaseInitializer : DropCreateDatabaseAlways + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; +} +public class IncludeMembersSelectFirstOrDefaultWithSubqueryMapFrom : AutoMapperSpecBase, IAsyncLifetime +{ + class Source + { + public int Id { get; set; } + public string Name { get; set; } + public List InnerSourceWrappers { get; set; } = new List(); + public List OtherInnerSources { get; set; } = new List(); + } + class InnerSourceWrapper + { + public int Id { get; set; } + public InnerSource InnerSource { get; set; } + } + class InnerSource + { + public int Id { get; set; } + public string Name { get; set; } + public List InnerSourceDetailsWrapper { get; } = new List(); + } + class InnerSourceDetailsWrapper + { + public int Id { get; set; } + public InnerSourceDetails InnerSourceDetails { get; set; } + } + class InnerSourceDetails + { + public int Id { get; set; } + public string Description { get; set; } + public string Publisher { get; set; } + } + class OtherInnerSource + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public List OtherInnerSourceDetails { get; } = new List(); + } + class OtherInnerSourceDetails + { + public int Id { get; set; } + public string Title { get; set; } + public string Author { get; set; } + } + class Destination + { + public int Id { get; set; } + public string Name { get; set; } + public DestinationDetails Details { get; set; } + public OtherDestinationDetails OtherDetails { get; set; } + } + class DestinationDetails + { + public string Description { get; set; } + public string Publisher { get; set; } + } + class OtherDestinationDetails + { + public string Title { get; set; } + public string Author { get; set; } + } + class Context : LocalDbContext + { + public DbSet Sources { get; set; } + } + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(Context context) { - protected override void Seed(Context context) + var source = new Source { - var source = new Source - { - Name = "name", - InnerSourceWrappers = { new InnerSourceWrapper { InnerSource = new InnerSource { InnerSourceDetailsWrapper = { new InnerSourceDetailsWrapper { InnerSourceDetails = new InnerSourceDetails { Description = "description", Publisher = "publisher" } } } } } + Name = "name", + InnerSourceWrappers = { new InnerSourceWrapper { InnerSource = new InnerSource { InnerSourceDetailsWrapper = { new InnerSourceDetailsWrapper { InnerSourceDetails = new InnerSourceDetails { Description = "description", Publisher = "publisher" } } } } } }, - OtherInnerSources = { new OtherInnerSource { OtherInnerSourceDetails = { new OtherInnerSourceDetails { Title = "title", Author = "author" } } } } - }; - context.Sources.Add(source); - base.Seed(context); - } - } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection().IncludeMembers(s => s.InnerSourceWrappers.Select(s => s.InnerSource).FirstOrDefault(), s => s.OtherInnerSources.Select(s=>s).FirstOrDefault()); - cfg.CreateProjection(MemberList.None).ForMember(d => d.Details, o => o.MapFrom(s => s.InnerSourceDetailsWrapper.Select(s => s.InnerSourceDetails).FirstOrDefault())); - cfg.CreateProjection(MemberList.None).ForMember(d => d.OtherDetails, o => o.MapFrom(s => s.OtherInnerSourceDetails.Select(s => s).FirstOrDefault())); - cfg.CreateProjection(); - cfg.CreateProjection(); - }); - [Fact] - public void Should_flatten() - { - using (var context = new Context()) - { - var projectTo = ProjectTo(context.Sources); - FirstOrDefaultCounter.Assert(projectTo, 4); - var result = projectTo.Single(); - result.Name.ShouldBe("name"); - result.Details.Description.ShouldBe("description"); - result.Details.Publisher.ShouldBe("publisher"); - result.OtherDetails.Title.ShouldBe("title"); - result.OtherDetails.Author.ShouldBe("author"); - } + OtherInnerSources = { new OtherInnerSource { OtherInnerSourceDetails = { new OtherInnerSourceDetails { Title = "title", Author = "author" } } } } + }; + context.Sources.Add(source); + base.Seed(context); } } - public class SubqueryMapFromWithIncludeMembersFirstOrDefault : AutoMapperSpecBase + protected override MapperConfiguration CreateConfiguration() => new(cfg => { - class Source - { - public int Id { get; set; } - public string Name { get; set; } - public List InnerSources { get; set; } = new List(); - public List OtherInnerSources { get; set; } = new List(); - } - class InnerSource - { - public int Id { get; set; } - public string Name { get; set; } - public List InnerSourceDetails { get; } = new List(); - } - class InnerSourceDetails - { - public int Id { get; set; } - public string Description { get; set; } - public string Publisher { get; set; } - } - class OtherInnerSource - { - public int Id { get; set; } - public string Name { get; set; } - public string Description { get; set; } - public List OtherInnerSourceDetails { get; } = new List(); - } - class OtherInnerSourceDetails - { - public int Id { get; set; } - public string Title { get; set; } - public string Author { get; set; } - } - class Destination - { - public int Id { get; set; } - public string Name { get; set; } - public DestinationDetails Details { get; set; } - public OtherDestinationDetails OtherDetails { get; set; } - } - class DestinationDetails - { - public string Description { get; set; } - public string Publisher { get; set; } - } - class OtherDestinationDetails + cfg.CreateProjection().IncludeMembers(s => s.InnerSourceWrappers.Select(s => s.InnerSource).FirstOrDefault(), s => s.OtherInnerSources.Select(s=>s).FirstOrDefault()); + cfg.CreateProjection(MemberList.None).ForMember(d => d.Details, o => o.MapFrom(s => s.InnerSourceDetailsWrapper.Select(s => s.InnerSourceDetails).FirstOrDefault())); + cfg.CreateProjection(MemberList.None).ForMember(d => d.OtherDetails, o => o.MapFrom(s => s.OtherInnerSourceDetails.Select(s => s).FirstOrDefault())); + cfg.CreateProjection(); + cfg.CreateProjection(); + }); + [Fact] + public void Should_flatten() + { + using (var context = new Context()) { - public string Title { get; set; } - public string Author { get; set; } + var projectTo = ProjectTo(context.Sources); + FirstOrDefaultCounter.Assert(projectTo, 4); + var result = projectTo.Single(); + result.Name.ShouldBe("name"); + result.Details.Description.ShouldBe("description"); + result.Details.Publisher.ShouldBe("publisher"); + result.OtherDetails.Title.ShouldBe("title"); + result.OtherDetails.Author.ShouldBe("author"); } - class Context : DbContext - { - public Context() - { - Database.SetInitializer(new DatabaseInitializer()); - } + } - public DbSet Sources { get; set; } - } - class DatabaseInitializer : DropCreateDatabaseAlways - { - protected override void Seed(Context context) - { - var source = new Source - { - Name = "name", - InnerSources = { new InnerSource { InnerSourceDetails = { new InnerSourceDetails { Description = "description", Publisher = "publisher" } } } }, - OtherInnerSources = { new OtherInnerSource { OtherInnerSourceDetails = { new OtherInnerSourceDetails { Title = "title", Author = "author" } } } } - }; - context.Sources.Add(source); - base.Seed(context); - } - } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection() - .ForMember(d => d.Details, o => o.MapFrom(s => s.InnerSources.FirstOrDefault())) - .ForMember(d => d.OtherDetails, o => o.MapFrom(s => s.OtherInnerSources.FirstOrDefault())); - cfg.CreateProjection().IncludeMembers(s => s.InnerSourceDetails.FirstOrDefault()); - cfg.CreateProjection().IncludeMembers(s => s.OtherInnerSourceDetails.FirstOrDefault()); - cfg.CreateProjection(); - cfg.CreateProjection(); - }); - [Fact] - public void Should_flatten() + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; +} +public class SubqueryMapFromWithIncludeMembersFirstOrDefault : AutoMapperSpecBase, IAsyncLifetime +{ + class Source + { + public int Id { get; set; } + public string Name { get; set; } + public List InnerSources { get; set; } = new List(); + public List OtherInnerSources { get; set; } = new List(); + } + class InnerSource + { + public int Id { get; set; } + public string Name { get; set; } + public List InnerSourceDetails { get; } = new List(); + } + class InnerSourceDetails + { + public int Id { get; set; } + public string Description { get; set; } + public string Publisher { get; set; } + } + class OtherInnerSource + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public List OtherInnerSourceDetails { get; } = new List(); + } + class OtherInnerSourceDetails + { + public int Id { get; set; } + public string Title { get; set; } + public string Author { get; set; } + } + class Destination + { + public int Id { get; set; } + public string Name { get; set; } + public DestinationDetails Details { get; set; } + public OtherDestinationDetails OtherDetails { get; set; } + } + class DestinationDetails + { + public string Description { get; set; } + public string Publisher { get; set; } + } + class OtherDestinationDetails + { + public string Title { get; set; } + public string Author { get; set; } + } + class Context : LocalDbContext + { + public DbSet Sources { get; set; } + } + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(Context context) { - using (var context = new Context()) + var source = new Source { - var projectTo = ProjectTo(context.Sources); - FirstOrDefaultCounter.Assert(projectTo, 6); - var result = projectTo.Single(); - result.Name.ShouldBe("name"); - result.Details.Description.ShouldBe("description"); - result.Details.Publisher.ShouldBe("publisher"); - result.OtherDetails.Title.ShouldBe("title"); - result.OtherDetails.Author.ShouldBe("author"); - } + Name = "name", + InnerSources = { new InnerSource { InnerSourceDetails = { new InnerSourceDetails { Description = "description", Publisher = "publisher" } } } }, + OtherInnerSources = { new OtherInnerSource { OtherInnerSourceDetails = { new OtherInnerSourceDetails { Title = "title", Author = "author" } } } } + }; + context.Sources.Add(source); + base.Seed(context); } } - public class SubqueryMapFromWithIncludeMembersSelectFirstOrDefault : AutoMapperSpecBase + protected override MapperConfiguration CreateConfiguration() => new(cfg => { - class Source - { - public int Id { get; set; } - public string Name { get; set; } - public List InnerSources { get; set; } = new List(); - public List OtherInnerSources { get; set; } = new List(); - } - class InnerSource - { - public int Id { get; set; } - public string Name { get; set; } - public List InnerSourceDetails { get; } = new List(); - } - class InnerSourceDetails - { - public int Id { get; set; } - public string Description { get; set; } - public string Publisher { get; set; } - } - class OtherInnerSource - { - public int Id { get; set; } - public string Name { get; set; } - public string Description { get; set; } - public List OtherInnerSourceDetails { get; } = new List(); - } - class OtherInnerSourceDetails - { - public int Id { get; set; } - public string Title { get; set; } - public string Author { get; set; } - } - class Destination - { - public int Id { get; set; } - public string Name { get; set; } - public DestinationDetails Details { get; set; } - public OtherDestinationDetails OtherDetails { get; set; } - } - class DestinationDetails - { - public string Description { get; set; } - public string Publisher { get; set; } - } - class OtherDestinationDetails + cfg.CreateProjection() + .ForMember(d => d.Details, o => o.MapFrom(s => s.InnerSources.FirstOrDefault())) + .ForMember(d => d.OtherDetails, o => o.MapFrom(s => s.OtherInnerSources.FirstOrDefault())); + cfg.CreateProjection().IncludeMembers(s => s.InnerSourceDetails.FirstOrDefault()); + cfg.CreateProjection().IncludeMembers(s => s.OtherInnerSourceDetails.FirstOrDefault()); + cfg.CreateProjection(); + cfg.CreateProjection(); + }); + [Fact] + public void Should_flatten() + { + using (var context = new Context()) { - public string Title { get; set; } - public string Author { get; set; } + var projectTo = ProjectTo(context.Sources); + FirstOrDefaultCounter.Assert(projectTo, 6); + var result = projectTo.Single(); + result.Name.ShouldBe("name"); + result.Details.Description.ShouldBe("description"); + result.Details.Publisher.ShouldBe("publisher"); + result.OtherDetails.Title.ShouldBe("title"); + result.OtherDetails.Author.ShouldBe("author"); } - class Context : DbContext - { - public Context() - { - Database.SetInitializer(new DatabaseInitializer()); - } + } - public DbSet Sources { get; set; } - } - class DatabaseInitializer : DropCreateDatabaseAlways - { - protected override void Seed(Context context) - { - var source = new Source - { - Name = "name", - InnerSources = { new InnerSource { InnerSourceDetails = { new InnerSourceDetails { Description = "description", Publisher = "publisher" } } } }, - OtherInnerSources = { new OtherInnerSource { OtherInnerSourceDetails = { new OtherInnerSourceDetails { Title = "title", Author = "author" } } } } - }; - context.Sources.Add(source); - base.Seed(context); - } - } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection() - .ForMember(d => d.Details, o => o.MapFrom(s => s.InnerSources.Select(s => s).FirstOrDefault())) - .ForMember(d => d.OtherDetails, o => o.MapFrom(s => s.OtherInnerSources.Select(s => s).FirstOrDefault())); - cfg.CreateProjection().IncludeMembers(s => s.InnerSourceDetails.Select(s => s).FirstOrDefault()); - cfg.CreateProjection().IncludeMembers(s => s.OtherInnerSourceDetails.Select(s => s).FirstOrDefault()); - cfg.CreateProjection(); - cfg.CreateProjection(); - }); - [Fact] - public void Should_flatten() + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; +} +public class SubqueryMapFromWithIncludeMembersSelectFirstOrDefault : AutoMapperSpecBase, IAsyncLifetime +{ + class Source + { + public int Id { get; set; } + public string Name { get; set; } + public List InnerSources { get; set; } = new List(); + public List OtherInnerSources { get; set; } = new List(); + } + class InnerSource + { + public int Id { get; set; } + public string Name { get; set; } + public List InnerSourceDetails { get; } = new List(); + } + class InnerSourceDetails + { + public int Id { get; set; } + public string Description { get; set; } + public string Publisher { get; set; } + } + class OtherInnerSource + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public List OtherInnerSourceDetails { get; } = new List(); + } + class OtherInnerSourceDetails + { + public int Id { get; set; } + public string Title { get; set; } + public string Author { get; set; } + } + class Destination + { + public int Id { get; set; } + public string Name { get; set; } + public DestinationDetails Details { get; set; } + public OtherDestinationDetails OtherDetails { get; set; } + } + class DestinationDetails + { + public string Description { get; set; } + public string Publisher { get; set; } + } + class OtherDestinationDetails + { + public string Title { get; set; } + public string Author { get; set; } + } + class Context : LocalDbContext + { + public DbSet Sources { get; set; } + } + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(Context context) { - using (var context = new Context()) + var source = new Source { - var projectTo = ProjectTo(context.Sources); - FirstOrDefaultCounter.Assert(projectTo, 6); - var result = projectTo.Single(); - result.Name.ShouldBe("name"); - result.Details.Description.ShouldBe("description"); - result.Details.Publisher.ShouldBe("publisher"); - result.OtherDetails.Title.ShouldBe("title"); - result.OtherDetails.Author.ShouldBe("author"); - } + Name = "name", + InnerSources = { new InnerSource { InnerSourceDetails = { new InnerSourceDetails { Description = "description", Publisher = "publisher" } } } }, + OtherInnerSources = { new OtherInnerSource { OtherInnerSourceDetails = { new OtherInnerSourceDetails { Title = "title", Author = "author" } } } } + }; + context.Sources.Add(source); + base.Seed(context); } } - public class SubqueryMapFromWithIncludeMembersSelectMemberFirstOrDefault : AutoMapperSpecBase + protected override MapperConfiguration CreateConfiguration() => new(cfg => { - class Source - { - public int Id { get; set; } - public string Name { get; set; } - public List InnerSourceWrappers { get; set; } = new List(); - public List OtherInnerSources { get; set; } = new List(); - } - class InnerSourceWrapper - { - public int Id { get; set; } - public InnerSource InnerSource { get; set; } - } - class InnerSource - { - public int Id { get; set; } - public string Name { get; set; } - public List InnerSourceDetailsWrapper { get; } = new List(); - } - class InnerSourceDetailsWrapper - { - public int Id { get; set; } - public InnerSourceDetails InnerSourceDetails { get; set; } - } - class InnerSourceDetails - { - public int Id { get; set; } - public string Description { get; set; } - public string Publisher { get; set; } - } - class OtherInnerSource - { - public int Id { get; set; } - public string Name { get; set; } - public string Description { get; set; } - public List OtherInnerSourceDetails { get; } = new List(); - } - class OtherInnerSourceDetails - { - public int Id { get; set; } - public string Title { get; set; } - public string Author { get; set; } - } - class Destination - { - public int Id { get; set; } - public string Name { get; set; } - public DestinationDetails Details { get; set; } - public OtherDestinationDetails OtherDetails { get; set; } - } - class DestinationDetails - { - public string Description { get; set; } - public string Publisher { get; set; } - } - class OtherDestinationDetails + cfg.CreateProjection() + .ForMember(d => d.Details, o => o.MapFrom(s => s.InnerSources.Select(s => s).FirstOrDefault())) + .ForMember(d => d.OtherDetails, o => o.MapFrom(s => s.OtherInnerSources.Select(s => s).FirstOrDefault())); + cfg.CreateProjection().IncludeMembers(s => s.InnerSourceDetails.Select(s => s).FirstOrDefault()); + cfg.CreateProjection().IncludeMembers(s => s.OtherInnerSourceDetails.Select(s => s).FirstOrDefault()); + cfg.CreateProjection(); + cfg.CreateProjection(); + }); + [Fact] + public void Should_flatten() + { + using (var context = new Context()) { - public string Title { get; set; } - public string Author { get; set; } + var projectTo = ProjectTo(context.Sources); + FirstOrDefaultCounter.Assert(projectTo, 6); + var result = projectTo.Single(); + result.Name.ShouldBe("name"); + result.Details.Description.ShouldBe("description"); + result.Details.Publisher.ShouldBe("publisher"); + result.OtherDetails.Title.ShouldBe("title"); + result.OtherDetails.Author.ShouldBe("author"); } - class Context : DbContext - { - public Context() - { - Database.SetInitializer(new DatabaseInitializer()); - } + } - public DbSet Sources { get; set; } - } - class DatabaseInitializer : DropCreateDatabaseAlways + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; +} +public class SubqueryMapFromWithIncludeMembersSelectMemberFirstOrDefault : AutoMapperSpecBase, IAsyncLifetime +{ + class Source + { + public int Id { get; set; } + public string Name { get; set; } + public List InnerSourceWrappers { get; set; } = new List(); + public List OtherInnerSources { get; set; } = new List(); + } + class InnerSourceWrapper + { + public int Id { get; set; } + public InnerSource InnerSource { get; set; } + } + class InnerSource + { + public int Id { get; set; } + public string Name { get; set; } + public List InnerSourceDetailsWrapper { get; } = new List(); + } + class InnerSourceDetailsWrapper + { + public int Id { get; set; } + public InnerSourceDetails InnerSourceDetails { get; set; } + } + class InnerSourceDetails + { + public int Id { get; set; } + public string Description { get; set; } + public string Publisher { get; set; } + } + class OtherInnerSource + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public List OtherInnerSourceDetails { get; } = new List(); + } + class OtherInnerSourceDetails + { + public int Id { get; set; } + public string Title { get; set; } + public string Author { get; set; } + } + class Destination + { + public int Id { get; set; } + public string Name { get; set; } + public DestinationDetails Details { get; set; } + public OtherDestinationDetails OtherDetails { get; set; } + } + class DestinationDetails + { + public string Description { get; set; } + public string Publisher { get; set; } + } + class OtherDestinationDetails + { + public string Title { get; set; } + public string Author { get; set; } + } + class Context : LocalDbContext + { + public DbSet Sources { get; set; } + } + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(Context context) { - protected override void Seed(Context context) + var source = new Source { - var source = new Source - { - Name = "name", - InnerSourceWrappers = { new InnerSourceWrapper { InnerSource = new InnerSource { InnerSourceDetailsWrapper = { new InnerSourceDetailsWrapper { InnerSourceDetails = new InnerSourceDetails { Description = "description", Publisher = "publisher" } } } } } + Name = "name", + InnerSourceWrappers = { new InnerSourceWrapper { InnerSource = new InnerSource { InnerSourceDetailsWrapper = { new InnerSourceDetailsWrapper { InnerSourceDetails = new InnerSourceDetails { Description = "description", Publisher = "publisher" } } } } } }, - OtherInnerSources = { new OtherInnerSource { OtherInnerSourceDetails = { new OtherInnerSourceDetails { Title = "title", Author = "author" } } } } - }; - context.Sources.Add(source); - base.Seed(context); - } - } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection() - .ForMember(d => d.Details, o => o.MapFrom(s => s.InnerSourceWrappers.Select(s => s.InnerSource).FirstOrDefault())) - .ForMember(d => d.OtherDetails, o => o.MapFrom(s => s.OtherInnerSources.Select(s => s).FirstOrDefault())); - cfg.CreateProjection().IncludeMembers(s => s.InnerSourceDetailsWrapper.Select(s => s.InnerSourceDetails).FirstOrDefault()); - cfg.CreateProjection().IncludeMembers(s => s.OtherInnerSourceDetails.Select(s => s).FirstOrDefault()); - cfg.CreateProjection(); - cfg.CreateProjection(); - }); - [Fact] - public void Should_flatten() - { - using (var context = new Context()) - { - var projectTo = ProjectTo(context.Sources); - FirstOrDefaultCounter.Assert(projectTo, 6); - var result = projectTo.Single(); - result.Name.ShouldBe("name"); - result.Details.Description.ShouldBe("description"); - result.Details.Publisher.ShouldBe("publisher"); - result.OtherDetails.Title.ShouldBe("title"); - result.OtherDetails.Author.ShouldBe("author"); - } + OtherInnerSources = { new OtherInnerSource { OtherInnerSourceDetails = { new OtherInnerSourceDetails { Title = "title", Author = "author" } } } } + }; + context.Sources.Add(source); + base.Seed(context); } } - public class IncludeMembersWithMapFromExpression : AutoMapperSpecBase + protected override MapperConfiguration CreateConfiguration() => new(cfg => { - class Source - { - public int Id { get; set; } - public string Name { get; set; } - public InnerSource InnerSource { get; set; } - public OtherInnerSource OtherInnerSource { get; set; } - } - class InnerSource - { - public int Id { get; set; } - public string Name { get; set; } - public string Description1 { get; set; } - } - class OtherInnerSource - { - public int Id { get; set; } - public string Name { get; set; } - public string Description { get; set; } - public string Title1 { get; set; } - } - class Destination + cfg.CreateProjection() + .ForMember(d => d.Details, o => o.MapFrom(s => s.InnerSourceWrappers.Select(s => s.InnerSource).FirstOrDefault())) + .ForMember(d => d.OtherDetails, o => o.MapFrom(s => s.OtherInnerSources.Select(s => s).FirstOrDefault())); + cfg.CreateProjection().IncludeMembers(s => s.InnerSourceDetailsWrapper.Select(s => s.InnerSourceDetails).FirstOrDefault()); + cfg.CreateProjection().IncludeMembers(s => s.OtherInnerSourceDetails.Select(s => s).FirstOrDefault()); + cfg.CreateProjection(); + cfg.CreateProjection(); + }); + [Fact] + public void Should_flatten() + { + using (var context = new Context()) { - public int Id { get; set; } - public string Name { get; set; } - public string Description { get; set; } - public string Title { get; set; } + var projectTo = ProjectTo(context.Sources); + FirstOrDefaultCounter.Assert(projectTo, 6); + var result = projectTo.Single(); + result.Name.ShouldBe("name"); + result.Details.Description.ShouldBe("description"); + result.Details.Publisher.ShouldBe("publisher"); + result.OtherDetails.Title.ShouldBe("title"); + result.OtherDetails.Author.ShouldBe("author"); } - class Context : DbContext - { - public Context() - { - Database.SetInitializer(new DatabaseInitializer()); - } + } - public DbSet Sources { get; set; } - } + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); - class DatabaseInitializer : DropCreateDatabaseAlways - { - protected override void Seed(Context context) - { - var source = new Source { Name = "name", InnerSource = new InnerSource { Description1 = "description" }, OtherInnerSource = new OtherInnerSource { Title1 = "title" } }; - context.Sources.Add(source); - base.Seed(context); - } - } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection().IncludeMembers(s => s.InnerSource, s => s.OtherInnerSource); - cfg.CreateProjection(MemberList.None).ForMember(d=>d.Description, o=>o.MapFrom(s=>s.Description1)); - cfg.CreateProjection(MemberList.None).ForMember(d=>d.Title, o=>o.MapFrom(s=>s.Title1)); - }); - [Fact] - public void Should_flatten_with_MapFrom() - { - using(var context = new Context()) - { - var result = ProjectTo(context.Sources).Single(); - result.Name.ShouldBe("name"); - result.Description.ShouldBe("description"); - result.Title.ShouldBe("title"); - } - } + await initializer.Migrate(); } - public class IncludeMembersWithNullSubstitute : AutoMapperSpecBase + public Task DisposeAsync() => Task.CompletedTask; +} +public class IncludeMembersWithMapFromExpression : AutoMapperSpecBase, IAsyncLifetime +{ + class Source { - class Source - { - public int Id { get; set; } - public string Name { get; set; } - public InnerSource InnerSource { get; set; } - public OtherInnerSource OtherInnerSource { get; set; } - } - class InnerSource - { - public int Id { get; set; } - public string Name { get; set; } - public int? Code { get; set; } - } - class OtherInnerSource + public int Id { get; set; } + public string Name { get; set; } + public InnerSource InnerSource { get; set; } + public OtherInnerSource OtherInnerSource { get; set; } + } + class InnerSource + { + public int Id { get; set; } + public string Name { get; set; } + public string Description1 { get; set; } + } + class OtherInnerSource + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public string Title1 { get; set; } + } + class Destination + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public string Title { get; set; } + } + class Context : LocalDbContext + { + public DbSet Sources { get; set; } + } + + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(Context context) { - public int Id { get; set; } - public string Name { get; set; } - public int? Code { get; set; } - public int? OtherCode { get; set; } + var source = new Source { Name = "name", InnerSource = new InnerSource { Description1 = "description" }, OtherInnerSource = new OtherInnerSource { Title1 = "title" } }; + context.Sources.Add(source); + base.Seed(context); } - class Destination + } + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection().IncludeMembers(s => s.InnerSource, s => s.OtherInnerSource); + cfg.CreateProjection(MemberList.None).ForMember(d=>d.Description, o=>o.MapFrom(s=>s.Description1)); + cfg.CreateProjection(MemberList.None).ForMember(d=>d.Title, o=>o.MapFrom(s=>s.Title1)); + }); + [Fact] + public void Should_flatten_with_MapFrom() + { + using(var context = new Context()) { - public int Id { get; set; } - public string Name { get; set; } - public int Code { get; set; } - public int OtherCode { get; set; } + var result = ProjectTo(context.Sources).Single(); + result.Name.ShouldBe("name"); + result.Description.ShouldBe("description"); + result.Title.ShouldBe("title"); } - class Context : DbContext - { - public Context() - { - Database.SetInitializer(new DatabaseInitializer()); - } + } - public DbSet Sources { get; set; } - } + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); - class DatabaseInitializer : DropCreateDatabaseAlways - { - protected override void Seed(Context context) - { - var source = new Source { Name = "name" }; - context.Sources.Add(source); - base.Seed(context); - } - } + await initializer.Migrate(); + } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection().IncludeMembers(s => s.InnerSource, s => s.OtherInnerSource); - cfg.CreateProjection(MemberList.None).ForMember(d => d.Code, o => o.NullSubstitute(5)); - cfg.CreateProjection(MemberList.None).ForMember(d => d.OtherCode, o => o.NullSubstitute(7)); - }); - [Fact] - public void Should_flatten() - { - using(var context = new Context()) - { - var result = ProjectTo(context.Sources).Single(); - result.Name.ShouldBe("name"); - result.Code.ShouldBe(5); - result.OtherCode.ShouldBe(7); - } - } + public Task DisposeAsync() => Task.CompletedTask; +} + +public class IncludeMembersWithNullSubstitute : AutoMapperSpecBase, IAsyncLifetime +{ + class Source + { + public int Id { get; set; } + public string Name { get; set; } + public InnerSource InnerSource { get; set; } + public OtherInnerSource OtherInnerSource { get; set; } } - public class IncludeMembersMembersFirstOrDefaultWithNullSubstitute : AutoMapperSpecBase + class InnerSource { - class Source - { - public int Id { get; set; } - public string Name { get; set; } - public List InnerSources { get; set; } = new List(); - public List OtherInnerSources { get; set; } = new List(); - } - class InnerSource - { - public int Id { get; set; } - public string Name { get; set; } - public int? Code { get; set; } - } - class OtherInnerSource - { - public int Id { get; set; } - public string Name { get; set; } - public int? Code { get; set; } - public int? OtherCode { get; set; } - } - class Destination - { - public int Id { get; set; } - public string Name { get; set; } - public int Code { get; set; } - public int OtherCode { get; set; } - } - class Context : DbContext - { - public Context() - { - Database.SetInitializer(new DatabaseInitializer()); - } + public int Id { get; set; } + public string Name { get; set; } + public int? Code { get; set; } + } + class OtherInnerSource + { + public int Id { get; set; } + public string Name { get; set; } + public int? Code { get; set; } + public int? OtherCode { get; set; } + } + class Destination + { + public int Id { get; set; } + public string Name { get; set; } + public int Code { get; set; } + public int OtherCode { get; set; } + } + class Context : LocalDbContext + { + public DbSet Sources { get; set; } + } - public DbSet Sources { get; set; } - } - class DatabaseInitializer : DropCreateDatabaseAlways - { - protected override void Seed(Context context) - { - var source = new Source { Name = "name" }; - context.Sources.Add(source); - base.Seed(context); - } - } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection().IncludeMembers(s => s.InnerSources.FirstOrDefault(), s => s.OtherInnerSources.FirstOrDefault()); - cfg.CreateProjection(MemberList.None).ForMember(d => d.Code, o => o.NullSubstitute(5)); - cfg.CreateProjection(MemberList.None).ForMember(d => d.OtherCode, o => o.NullSubstitute(7)); - }); - [Fact] - public void Should_flatten() + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(Context context) { - using (var context = new Context()) - { - var projectTo = ProjectTo(context.Sources); - FirstOrDefaultCounter.Assert(projectTo, 2); - var result = projectTo.Single(); - result.Name.ShouldBe("name"); - result.Code.ShouldBe(5); - result.OtherCode.ShouldBe(7); - } + var source = new Source { Name = "name" }; + context.Sources.Add(source); + base.Seed(context); } } - public class CascadedIncludeMembers : AutoMapperSpecBase + + protected override MapperConfiguration CreateConfiguration() => new(cfg => { - public class Source - { - public int Id{ get; set; } - public Level1 FieldLevel1{ get; set; } - } - public class Level1 - { - public int Id{ get; set; } - public Level2 FieldLevel2{ get; set; } - } - public class Level2 + cfg.CreateProjection().IncludeMembers(s => s.InnerSource, s => s.OtherInnerSource); + cfg.CreateProjection(MemberList.None).ForMember(d => d.Code, o => o.NullSubstitute(5)); + cfg.CreateProjection(MemberList.None).ForMember(d => d.OtherCode, o => o.NullSubstitute(7)); + }); + [Fact] + public void Should_flatten() + { + using(var context = new Context()) { - public int Id{ get; set; } - public long TheField{ get; set; } + var result = ProjectTo(context.Sources).Single(); + result.Name.ShouldBe("name"); + result.Code.ShouldBe(5); + result.OtherCode.ShouldBe(7); } - public class Destination + } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; +} +public class IncludeMembersMembersFirstOrDefaultWithNullSubstitute : AutoMapperSpecBase, IAsyncLifetime +{ + class Source + { + public int Id { get; set; } + public string Name { get; set; } + public List InnerSources { get; set; } = new List(); + public List OtherInnerSources { get; set; } = new List(); + } + class InnerSource + { + public int Id { get; set; } + public string Name { get; set; } + public int? Code { get; set; } + } + class OtherInnerSource + { + public int Id { get; set; } + public string Name { get; set; } + public int? Code { get; set; } + public int? OtherCode { get; set; } + } + class Destination + { + public int Id { get; set; } + public string Name { get; set; } + public int Code { get; set; } + public int OtherCode { get; set; } + } + class Context : LocalDbContext + { + public DbSet Sources { get; set; } + } + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(Context context) { - public int Id{ get; set; } - public long TheField{ get; set; } + var source = new Source { Name = "name" }; + context.Sources.Add(source); + base.Seed(context); } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection().IncludeMembers(s => s.FieldLevel1); - cfg.CreateProjection(MemberList.None).IncludeMembers(s => s.FieldLevel2); - cfg.CreateProjection(MemberList.None); - }); - class Context : DbContext + } + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection().IncludeMembers(s => s.InnerSources.FirstOrDefault(), s => s.OtherInnerSources.FirstOrDefault()); + cfg.CreateProjection(MemberList.None).ForMember(d => d.Code, o => o.NullSubstitute(5)); + cfg.CreateProjection(MemberList.None).ForMember(d => d.OtherCode, o => o.NullSubstitute(7)); + }); + [Fact] + public void Should_flatten() + { + using (var context = new Context()) { - public Context() - { - Database.SetInitializer(new DatabaseInitializer()); - } - public DbSet Sources { get; set; } + var projectTo = ProjectTo(context.Sources); + FirstOrDefaultCounter.Assert(projectTo, 2); + var result = projectTo.Single(); + result.Name.ShouldBe("name"); + result.Code.ShouldBe(5); + result.OtherCode.ShouldBe(7); } - class DatabaseInitializer : DropCreateDatabaseAlways + } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; +} +public class CascadedIncludeMembers : AutoMapperSpecBase, IAsyncLifetime +{ + public class Source + { + public int Id{ get; set; } + public Level1 FieldLevel1{ get; set; } + } + public class Level1 + { + public int Id{ get; set; } + public Level2 FieldLevel2{ get; set; } + } + public class Level2 + { + public int Id{ get; set; } + public long TheField{ get; set; } + } + public class Destination + { + public int Id{ get; set; } + public long TheField{ get; set; } + } + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection().IncludeMembers(s => s.FieldLevel1); + cfg.CreateProjection(MemberList.None).IncludeMembers(s => s.FieldLevel2); + cfg.CreateProjection(MemberList.None); + }); + class Context : LocalDbContext + { + public DbSet Sources { get; set; } + } + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(Context context) { - protected override void Seed(Context context) - { - var source = new Source { Id = 1, FieldLevel1 = new Level1 { FieldLevel2 = new Level2 { TheField = 2 } } }; - context.Sources.Add(source); - base.Seed(context); - } + var source = new Source { FieldLevel1 = new Level1 { FieldLevel2 = new Level2 { TheField = 2 } } }; + context.Sources.Add(source); + base.Seed(context); } - [Fact] - public void Should_flatten() + } + [Fact] + public void Should_flatten() + { + using (var context = new Context()) { - using (var context = new Context()) - { - var projectTo = ProjectTo(context.Sources); - var result = projectTo.Single(); - result.Id.ShouldBe(1); - result.TheField.ShouldBe(2); - } + var projectTo = ProjectTo(context.Sources); + var result = projectTo.Single(); + result.Id.ShouldBe(1); + result.TheField.ShouldBe(2); } } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/Infrastructure/TestDbConfiguration.cs b/src/IntegrationTests/Infrastructure/TestDbConfiguration.cs deleted file mode 100644 index d6eba06055..0000000000 --- a/src/IntegrationTests/Infrastructure/TestDbConfiguration.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Data.Entity; -using System.Data.Entity.Infrastructure; - -namespace AutoMapper.IntegrationTests.Net4 -{ - public class TestDbConfiguration : DbConfiguration - { - public TestDbConfiguration() - { - SetDefaultConnectionFactory(new LocalDbConnectionFactory("MSSQLLocalDB")); - } - } -} \ No newline at end of file diff --git a/src/IntegrationTests/Inheritance/DerivedComplexTypes.cs b/src/IntegrationTests/Inheritance/DerivedComplexTypes.cs index f49bb40e37..0a9c6a3f6a 100644 --- a/src/IntegrationTests/Inheritance/DerivedComplexTypes.cs +++ b/src/IntegrationTests/Inheritance/DerivedComplexTypes.cs @@ -1,88 +1,94 @@ using System.ComponentModel.DataAnnotations; -using System.Data.Entity; +using System.ComponentModel.DataAnnotations.Schema; using System.Linq; +using System.Threading.Tasks; +using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; using Shouldly; using Xunit; -namespace AutoMapper.IntegrationTests +namespace AutoMapper.IntegrationTests.Inheritance; + +public class DerivedComplexTypes : AutoMapperSpecBase, IAsyncLifetime { - using UnitTests; - using QueryableExtensions; - using System.ComponentModel.DataAnnotations.Schema; + [ComplexType] + public class LocalizedString + { + public string Value { get; set; } + } - public class DerivedComplexTypes : AutoMapperSpecBase + [ComplexType] + public class DerivedLocalizedString : LocalizedString { - [ComplexType] - public class LocalizedString - { - public string Value { get; set; } - } + } - [ComplexType] - public class DerivedLocalizedString : LocalizedString + public class Customer + { + public Customer() { } - public class Customer - { - public Customer() - { - } + [Key] + public int Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + public DerivedLocalizedString Address { get; set; } + } - [Key] - public int Id { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - public DerivedLocalizedString Address { get; set; } - } + public class CustomerViewModel + { + public string FirstName { get; set; } + public string LastName { get; set; } + public string Address { get; set; } + } - public class CustomerViewModel - { - public string FirstName { get; set; } - public string LastName { get; set; } - public string Address { get; set; } - } + public class Context : LocalDbContext + { + public DbSet Customers { get; set; } - public class Context : DbContext + protected override void OnModelCreating(ModelBuilder modelBuilder) { - public Context() - { - Database.SetInitializer(new DatabaseInitializer()); - } - - public DbSet Customers { get; set; } + modelBuilder.Entity().OwnsOne(c => c.Address); } + } - public class DatabaseInitializer : DropCreateDatabaseAlways + public class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(Context context) { - protected override void Seed(Context context) + context.Customers.Add(new Customer { - context.Customers.Add(new Customer - { - Id = 1, - FirstName = "Bob", - LastName = "Smith", - Address = new DerivedLocalizedString { Value = "home" } - }); + FirstName = "Bob", + LastName = "Smith", + Address = new DerivedLocalizedString { Value = "home" } + }); - base.Seed(context); - } + base.Seed(context); } + } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection(); - cfg.CreateProjection().ConvertUsing(v => v.Value); - }); + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection(); + cfg.CreateProjection().ConvertUsing(v => v.Value); + }); - [Fact] - public void Can_map_with_projection() + [Fact] + public void Can_map_with_projection() + { + using (var context = new Context()) { - using (var context = new Context()) - { - var customerVm = ProjectTo(context.Customers).First(); - customerVm.Address.ShouldBe("home"); - } + var customerVm = ProjectTo(context.Customers).First(); + customerVm.Address.ShouldBe("home"); } } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/Inheritance/OverrideDestinationMappingsTest.cs b/src/IntegrationTests/Inheritance/OverrideDestinationMappingsTest.cs index 8dcaa2f5a1..12afc48e77 100644 --- a/src/IntegrationTests/Inheritance/OverrideDestinationMappingsTest.cs +++ b/src/IntegrationTests/Inheritance/OverrideDestinationMappingsTest.cs @@ -1,91 +1,95 @@ -using AutoMapper; -using Xunit; -using System.Linq; -using Shouldly; -using System.Data.Entity; +using System.Linq; +using System.Threading.Tasks; using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; +using Shouldly; +using Xunit; + +namespace AutoMapper.IntegrationTests.Inheritance; -namespace AutoMapper.IntegrationTests.Net4 +public class OverrideDestinationMappingsTest : AutoMapperSpecBase, IAsyncLifetime { - public class OverrideDestinationMappingsTest : AutoMapperSpecBase + public class Context : LocalDbContext { - public class Context : DbContext - { - public Context() - { - Database.SetInitializer(new DatabaseInitializer()); - } - - public DbSet Entity { get; set; } - } + public DbSet Entity { get; set; } + } - public class DatabaseInitializer : CreateDatabaseIfNotExists + public class DatabaseInitializer : CreateDatabaseIfNotExists + { + protected override void Seed(Context context) { - protected override void Seed(Context context) + context.Entity.AddRange(new[] { - context.Entity.AddRange(new[] - { - new Entity { Id = 1, Child = new ChildEntity { SomeValue = "Alain Brito"} }, - new Entity { Id = 2, Child = new ChildEntity { SomeValue = "Jimmy Bogard"} }, - new Entity { Id = 3, Child = new ChildEntity { SomeValue = "Bill Gates"} } - }); - base.Seed(context); - } + new Entity { Child = new ChildEntity { SomeValue = "Alain Brito"} }, + new Entity { Child = new ChildEntity { SomeValue = "Jimmy Bogard"} }, + new Entity { Child = new ChildEntity { SomeValue = "Bill Gates"} } + }); + base.Seed(context); } + } - [Fact] - public void Map_WhenOverrideDestinationTypeAndSourceIsDerived_MustCreateOverriddenDestinationType() - { - Entity entity = LoadEntity(); + [Fact] + public void Map_WhenOverrideDestinationTypeAndSourceIsDerived_MustCreateOverriddenDestinationType() + { + Entity entity = LoadEntity(); - var model = Mapper.Map(entity); + var model = Mapper.Map(entity); - model.Child.ShouldBeOfType(); - } + model.Child.ShouldBeOfType(); + } - private static Entity LoadEntity() + private static Entity LoadEntity() + { + using(var context = new Context()) { - using(var context = new Context()) - { - return context.Entity.First(); - } + return context.Entity.Include(e => e.Child).First(); } + } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateMap(); + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateMap(); - cfg.CreateMap() - .Include() - .ForMember(x => x.SomeValue, x => x.Ignore()) - .As(); + cfg.CreateMap() + .Include() + .ForMember(x => x.SomeValue, x => x.Ignore()) + .As(); - cfg.CreateMap(); - }); + cfg.CreateMap(); + }); - public class Entity - { - public int Id { get; set; } - public ChildEntity Child { get; set; } - } + public class Entity + { + public int Id { get; set; } + public ChildEntity Child { get; set; } + } - public class ChildEntity - { - public string SomeValue { get; set; } - } + public class ChildEntity + { + public int Id { get; set; } + public string SomeValue { get; set; } + } - public class Model - { - public ChildModelBase Child { get; set; } - } + public class Model + { + public ChildModelBase Child { get; set; } + } - public abstract class ChildModelBase - { - public string SomeValue { get; set; } - } + public abstract class ChildModelBase + { + public string SomeValue { get; set; } + } - public class ChildModel : ChildModelBase - { - } + public class ChildModel : ChildModelBase + { } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/Inheritance/ProjectToAbstractType.cs b/src/IntegrationTests/Inheritance/ProjectToAbstractType.cs index a27bed060a..c5fc98bd9a 100644 --- a/src/IntegrationTests/Inheritance/ProjectToAbstractType.cs +++ b/src/IntegrationTests/Inheritance/ProjectToAbstractType.cs @@ -1,356 +1,363 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Data.Entity; using System.Linq; -using AutoMapper.QueryableExtensions; +using System.Threading.Tasks; using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; using Shouldly; using Xunit; -namespace AutoMapper.IntegrationTests.Net4 +namespace AutoMapper.IntegrationTests.Inheritance; + +public class ProjectToAbstractType : AutoMapperSpecBase, IAsyncLifetime { - public class ProjectToAbstractType : AutoMapperSpecBase + ITypeA[] _destinations; + + public interface ITypeA { - ITypeA[] _destinations; + int ID { get; set; } + string Name { get; set; } + } - public interface ITypeA - { - int ID { get; set; } - string Name { get; set; } - } + public class ConcreteTypeA : ITypeA + { + public int ID { get; set; } + public string Name { get; set; } + } - public class ConcreteTypeA : ITypeA + public class DbEntityA + { + public int ID { get; set; } + public string Name { get; set; } + } + + public class DatabaseInitializer : CreateDatabaseIfNotExists + { + protected override void Seed(Context context) { - public int ID { get; set; } - public string Name { get; set; } + context.EntityA.AddRange(new[] + { + new DbEntityA { Name = "Alain Brito"}, + new DbEntityA { Name = "Jimmy Bogard"}, + new DbEntityA { Name = "Bill Gates"} + }); + base.Seed(context); } + } + public class Context : LocalDbContext + { + public DbSet EntityA { get; set; } + } + + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateMap().As(); + cfg.CreateProjection(); + }); - public class DbEntityA + [Fact] + public void Should_project_to_abstract_type() + { + using(var context = new Context()) { - public int ID { get; set; } - public string Name { get; set; } + _destinations = ProjectTo(context.EntityA).ToArray(); } + _destinations.Length.ShouldBe(3); + _destinations[2].Name.ShouldBe("Bill Gates"); + } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; +} - public class DatabaseInitializer : CreateDatabaseIfNotExists +public class ProjectToInterface : AutoMapperSpecBase, IAsyncLifetime +{ + //Data Objects + public class DataLayer + { + public class BaseDbObject { - protected override void Seed(Context context) - { - context.EntityA.AddRange(new[] - { - new DbEntityA { ID = 1, Name = "Alain Brito"}, - new DbEntityA { ID = 2, Name = "Jimmy Bogard"}, - new DbEntityA { ID = 3, Name = "Bill Gates"} - }); - base.Seed(context); - } + public Guid Id { get; set; } } - public class Context : DbContext + public class Calendar : BaseDbObject { - public Context() - { - Database.SetInitializer(new DatabaseInitializer()); - } + public string Name { get; set; } + public Guid? ReferenceId { get; set; } + public Guid BusinessUnitId { get; set; } + public DateTime? ValidFrom { get; set; } + public DateTime? ValidTo { get; set; } - public DbSet EntityA { get; set; } + public virtual Calendar Reference { get; set; } + public virtual ICollection Days { get; set; } } - - protected override MapperConfiguration CreateConfiguration() => new(cfg => + public class CalendarDay : BaseDbObject { - cfg.CreateMap().As(); - cfg.CreateProjection(); - }); + public DateTime Date { get; set; } + public Guid DayTypeId { get; set; } + public Guid CalendarId { get; set; } + public bool Cancel { get; set; } + public bool Deleted { get; set; } + + public virtual ValidityDayType DayType { get; set; } + public virtual Calendar Calendar { get; set; } + } - [Fact] - public void Should_project_to_abstract_type() + public class ValidityDayType : BaseDbObject { - using(var context = new Context()) - { - _destinations = ProjectTo(context.EntityA).ToArray(); - } - _destinations.Length.ShouldBe(3); - _destinations[2].Name.ShouldBe("Bill Gates"); + public string Name { get; set; } + public string Acronym { get; set; } + + public virtual ICollection Days { get; set; } + // public virtual ICollection Signs { get; set; } } } - public class ProjectToInterface : AutoMapperSpecBase + public interface ICalendar { - //Data Objects - public class DataLayer - { - public class BaseDbObject - { - public Guid Id { get; set; } - } - public class Calendar : BaseDbObject - { - public string Name { get; set; } - public Guid? ReferenceId { get; set; } - public Guid BusinessUnitId { get; set; } - public DateTime? ValidFrom { get; set; } - public DateTime? ValidTo { get; set; } - - public virtual Calendar Reference { get; set; } - public virtual ICollection Days { get; set; } - } - public class CalendarDay : BaseDbObject - { - public DateTime Date { get; set; } - public Guid DayTypeId { get; set; } - public Guid CalendarId { get; set; } - public bool Cancel { get; set; } - public bool Deleted { get; set; } + Guid Id { get; } + string Name { get; } + Guid BusinessUnitId { get; } - public virtual ValidityDayType DayType { get; set; } - public virtual Calendar Calendar { get; set; } - } + ICalendar Reference { get; } + DateTime? ValidFrom { get; } + DateTime? ValidTo { get; } - public class ValidityDayType : BaseDbObject - { - public string Name { get; set; } - public string Acronym { get; set; } + ICollection Days { get; set; } + } - public virtual ICollection Days { get; set; } - // public virtual ICollection Signs { get; set; } - } - } + public interface ICalendarDay + { + Guid Id { get; } + DateTime Date { get; } + IValidityDayType DayType { get; } + ICalendar Calendar { get; } + bool Cancel { get; } + bool Deleted { get; } + } - public interface ICalendar - { - Guid Id { get; } - string Name { get; } - Guid BusinessUnitId { get; } + public interface IValidityDayType + { + Guid Id { get; } - ICalendar Reference { get; } - DateTime? ValidFrom { get; } - DateTime? ValidTo { get; } + string Name { get; } - ICollection Days { get; set; } - } + string Acronym { get; } - public interface ICalendarDay - { - Guid Id { get; } - DateTime Date { get; } - IValidityDayType DayType { get; } - ICalendar Calendar { get; } - bool Cancel { get; } - bool Deleted { get; } - } + // ICollection Signs { get; internal set; } = ImmutableList.Empty; - public interface IValidityDayType - { - Guid Id { get; } + ICollection Days { get; } + } - string Name { get; } + //Domain Models + public class Calendar : ICalendar + { + public Guid Id { get; internal set; } + public string Name { get; internal set; } + public Guid BusinessUnitId { get; internal set; } - string Acronym { get; } + public ICalendar Reference { get; internal set; } + public DateTime? ValidFrom { get; internal set; } + public DateTime? ValidTo { get; internal set; } - // ICollection Signs { get; internal set; } = ImmutableList.Empty; + public virtual ICollection Days { get; set; } + + internal Calendar() + { - ICollection Days { get; } } - //Domain Models - public class Calendar : ICalendar + public Calendar(string name, Guid businessUnitId, ICalendar reference, DateTime? validFrom, DateTime? validTo) { - public Guid Id { get; internal set; } - public string Name { get; internal set; } - public Guid BusinessUnitId { get; internal set; } + if(businessUnitId == Guid.Empty) throw new ArgumentException(); - public ICalendar Reference { get; internal set; } - public DateTime? ValidFrom { get; internal set; } - public DateTime? ValidTo { get; internal set; } + Name = name; + BusinessUnitId = businessUnitId; + Reference = reference; + ValidFrom = validFrom; + ValidTo = validTo; + } + } - public virtual ICollection Days { get; set; } + public class CalendarDay : ICalendarDay + { + public Guid Id { get; internal set; } + public DateTime Date { get; internal set; } + public IValidityDayType DayType { get; internal set; } + public ICalendar Calendar { get; internal set; } + public bool Cancel { get; private set; } + public bool Deleted { get; private set; } + + internal CalendarDay() + { - internal Calendar() - { + } - } + public CalendarDay(DateTime date, IValidityDayType dayType, ICalendar calendar) + { + DayType = dayType ?? throw new ArgumentNullException(); + Calendar = calendar ?? throw new ArgumentNullException(); + Date = date; + } - public Calendar(string name, Guid businessUnitId, ICalendar reference, DateTime? validFrom, DateTime? validTo) - { - if(businessUnitId == Guid.Empty) throw new ArgumentException(); - - Name = name; - BusinessUnitId = businessUnitId; - Reference = reference; - ValidFrom = validFrom; - ValidTo = validTo; - } + public void SetDeleted() + { + Deleted = true; } - public class CalendarDay : ICalendarDay + public void SetCancel() { - public Guid Id { get; internal set; } - public DateTime Date { get; internal set; } - public IValidityDayType DayType { get; internal set; } - public ICalendar Calendar { get; internal set; } - public bool Cancel { get; private set; } - public bool Deleted { get; private set; } - - internal CalendarDay() - { + Cancel = true; + } + } - } + public class ValidityDayType : IValidityDayType + { + public Guid Id { get; internal set; } - public CalendarDay(DateTime date, IValidityDayType dayType, ICalendar calendar) - { - DayType = dayType ?? throw new ArgumentNullException(); - Calendar = calendar ?? throw new ArgumentNullException(); - Date = date; - } + public string Name { get; internal set; } - public void SetDeleted() - { - Deleted = true; - } + public string Acronym { get; internal set; } - public void SetCancel() - { - Cancel = true; - } - } + public ICollection Days { get; internal set; } = new List(); - public class ValidityDayType : IValidityDayType + internal ValidityDayType() { - public Guid Id { get; internal set; } - - public string Name { get; internal set; } - - public string Acronym { get; internal set; } - - public ICollection Days { get; internal set; } = new List(); - internal ValidityDayType() - { + } - } + public ValidityDayType(string name, string acronym) + { + Name = name; + Acronym = acronym; + } - public ValidityDayType(string name, string acronym) - { - Name = name; - Acronym = acronym; - } + public ICalendarDay ApplyToDay(DateTime date, ICalendar calendar) + { + var day = new CalendarDay(date, this, calendar); + return day; + } - public ICalendarDay ApplyToDay(DateTime date, ICalendar calendar) - { - var day = new CalendarDay(date, this, calendar); - return day; - } + public IEnumerable GetCalendarDays(ICalendar calendar) + { + if(calendar == null) + throw new ArgumentNullException(); - public IEnumerable GetCalendarDays(ICalendar calendar) - { - if(calendar == null) - throw new ArgumentNullException(); + return Days.Where(d => d.Calendar == calendar); + } + } - return Days.Where(d => d.Calendar == calendar); - } + public class DatabaseInitializer : CreateDatabaseIfNotExists + { + protected override void Seed(Context context) + { + context.Calendars.AddRange(CreateCalendarList()); } - public class DatabaseInitializer : CreateDatabaseIfNotExists + private static List CreateCalendarList() { - protected override void Seed(Context context) + var dayType = new DataLayer.ValidityDayType() { - context.Calendars.AddRange(CreateCalendarList()); - } + Name = "WorkDays", + Acronym = "WD", + }; - private static List CreateCalendarList() + var day = new DataLayer.CalendarDay() { - var dayType = new DataLayer.ValidityDayType() - { - Name = "WorkDays", - Acronym = "WD", - }; - - var day = new DataLayer.CalendarDay() - { - Id = new Guid(), - Cancel = true, - Deleted = false, - DayType = dayType, - Date = DateTime.Parse("2018-03-31") - }; - - var cal1 = new DataLayer.Calendar() - { - Id = Guid.NewGuid(), - Name = "Regional 2018", - BusinessUnitId = Guid.NewGuid(), - ValidFrom = DateTime.Parse("2018-01-01"), - ValidTo = null, - Days = new Collection() - { - day - } - }; - - var cal2 = new DataLayer.Calendar() - { - Id = Guid.NewGuid(), - Name = "City 2018", - ReferenceId = cal1.Id, - Reference = cal1, - BusinessUnitId = Guid.NewGuid(), - ValidFrom = DateTime.Parse("2018-01-01"), - ValidTo = null, - Days = new Collection() - }; - - var dataCalendars = new List() + Id = new Guid(), + Cancel = true, + Deleted = false, + DayType = dayType, + Date = DateTime.Parse("2018-03-31") + }; + + var cal1 = new DataLayer.Calendar() + { + Id = Guid.NewGuid(), + Name = "Regional 2018", + BusinessUnitId = Guid.NewGuid(), + ValidFrom = DateTime.Parse("2018-01-01"), + ValidTo = null, + Days = new Collection() { - cal1, cal2 - }; - return dataCalendars; - } - } + day + } + }; - public class Context : DbContext - { - public Context() + var cal2 = new DataLayer.Calendar() { - Database.SetInitializer(new DatabaseInitializer()); - } - - public DbSet Calendars { get; set; } + Id = Guid.NewGuid(), + Name = "City 2018", + ReferenceId = cal1.Id, + Reference = cal1, + BusinessUnitId = Guid.NewGuid(), + ValidFrom = DateTime.Parse("2018-01-01"), + ValidTo = null, + Days = new Collection() + }; + + var dataCalendars = new List() + { + cal1, cal2 + }; + return dataCalendars; } + } + + public class Context : LocalDbContext + { + public DbSet Calendars { get; set; } + } - protected override MapperConfiguration CreateConfiguration() => new(cfg => cfg.AddProfile()); + protected override MapperConfiguration CreateConfiguration() => new(cfg => cfg.AddProfile()); - [Fact] - public void Should_project_to_abstract_type() + [Fact] + public void Should_project_to_abstract_type() + { + using(var context = new Context()) { - using(var context = new Context()) - { - var domainCalendars = ProjectTo(context.Calendars).ToList(); - domainCalendars.Count.ShouldBe(2); - } + var domainCalendars = ProjectTo(context.Calendars).ToList(); + domainCalendars.Count.ShouldBe(2); } + } - public class MyProfile : Profile + public class MyProfile : Profile + { + public MyProfile() { - public MyProfile() - { - DisableConstructorMapping(); + DisableConstructorMapping(); - CreateMap().As(); - CreateProjection(); + CreateMap().As(); + CreateProjection(); - CreateMap().As(); - CreateProjection(); - //.ForMember(d => d.DayType, opt => opt.Ignore()); + CreateMap().As(); + CreateProjection(); + //.ForMember(d => d.DayType, opt => opt.Ignore()); - //Include to mapping -> this causes the exception! - CreateMap().As(); - CreateProjection(); + //Include to mapping -> this causes the exception! + CreateMap().As(); + CreateProjection(); - CreateProjection(); + CreateProjection(); - CreateProjection(); + CreateProjection(); - CreateProjection(); - } + CreateProjection(); } } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/Inheritance/ProxyTests.cs b/src/IntegrationTests/Inheritance/ProxyTests.cs index 8434f647f9..3eb35328e0 100644 --- a/src/IntegrationTests/Inheritance/ProxyTests.cs +++ b/src/IntegrationTests/Inheritance/ProxyTests.cs @@ -1,115 +1,122 @@ -namespace AutoMapper.IntegrationTests.Net4 +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; +using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; +using Xunit; + +namespace AutoMapper.IntegrationTests.Inheritance; + +public class ProxyTests : IAsyncLifetime { - using AutoMapper.UnitTests; - using System.Collections.Generic; - using System.ComponentModel.DataAnnotations; - using System.Data.Entity; - using System.Linq; - using Xunit; - - public class ProxyTests + [Fact] + public void Test() + { + var config = new MapperConfiguration(cfg => { + cfg.CreateMap().Include(); + cfg.CreateMap(); + cfg.CreateMap(); + }); + config.AssertConfigurationIsValid(); + + var context = new ClientContext(); + var course = context.TrainingCourses.FirstOrDefault(n => n.CourseName == "Course 1"); + var mapper = config.CreateMapper(); + var dto = mapper.Map(course); + } + + class DatabaseInitializer : DropCreateDatabaseAlways { - [Fact] - public void Test() + protected override void Seed(ClientContext context) { - Database.SetInitializer(new Initializer()); - - var config = new MapperConfiguration(cfg => { - cfg.CreateMap().Include(); - cfg.CreateMap(); - cfg.CreateMap(); - }); - config.AssertConfigurationIsValid(); - - var context = new ClientContext(); - var course = context.TrainingCourses.FirstOrDefault(n => n.CourseName == "Course 1"); - var mapper = config.CreateMapper(); - var dto = mapper.Map(course); + var course = new TrainingCourse { CourseName = "Course 1" }; + context.TrainingCourses.Add(course); + var content = new TrainingContent { ContentName = "Content 1", Course = course }; + context.TrainingContents.Add(content); + course.Content.Add(content); } + } - class Initializer : DropCreateDatabaseAlways + class ClientContext : LocalDbContext + { + public ClientContext() { - protected override void Seed(ClientContext context) - { - var course = new TrainingCourse { CourseName = "Course 1" }; - context.TrainingCourses.Add(course); - var content = new TrainingContent { ContentName = "Content 1", Course = course }; - context.TrainingContents.Add(content); - course.Content.Add(content); - } } - class ClientContext : DbContext - { - public ClientContext() - { - } + public DbSet TrainingCourses { get; set; } + public DbSet TrainingContents { get; set; } + } - public DbSet TrainingCourses { get; set; } - public DbSet TrainingContents { get; set; } + public class TrainingCourse + { + public TrainingCourse() + { + Content = new List(); } - public class TrainingCourse + public TrainingCourse(TrainingCourse entity, IMapper mapper) { - public TrainingCourse() - { - Content = new List(); - } + mapper.Map(entity, this); + } - public TrainingCourse(TrainingCourse entity, IMapper mapper) - { - mapper.Map(entity, this); - } + [Key] + public int CourseId { get; set; } - [Key] - public int CourseId { get; set; } + public string CourseName { get; set; } - public string CourseName { get; set; } + public virtual ICollection Content { get; set; } + } - public virtual ICollection Content { get; set; } + public class TrainingContent + { + public TrainingContent() + { } - public class TrainingContent - { - public TrainingContent() - { - } + [Key] + public int ContentId { get; set; } - [Key] - public int ContentId { get; set; } + public string ContentName { get; set; } - public string ContentName { get; set; } + public virtual TrainingCourse Course { get; set; } - public virtual TrainingCourse Course { get; set; } + // public int CourseId { get; set; } - // public int CourseId { get; set; } + } - } + public class TrainingCourseDto + { + public int CourseId { get; set; } - public class TrainingCourseDto - { - public int CourseId { get; set; } + public string CourseName { get; set; } - public string CourseName { get; set; } + public virtual ICollection Content { get; set; } + } - public virtual ICollection Content { get; set; } - } + public class ParentTrainingCourseDto : TrainingCourseDto + { + [IgnoreMap] + public override ICollection Content { get; set; } + } - public class ParentTrainingCourseDto : TrainingCourseDto - { - [IgnoreMap] - public override ICollection Content { get; set; } - } + public class TrainingContentDto + { + public int ContentId { get; set; } - public class TrainingContentDto - { - public int ContentId { get; set; } + public string ContentName { get; set; } + + public ParentTrainingCourseDto Course { get; set; } - public string ContentName { get; set; } + // public int CourseId { get; set; } + } - public ParentTrainingCourseDto Course { get; set; } + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); - // public int CourseId { get; set; } - } + await initializer.Migrate(); } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/Inheritance/QueryableInterfaceInheritanceIssue.cs b/src/IntegrationTests/Inheritance/QueryableInterfaceInheritanceIssue.cs index 9e683768f0..8af8b05b60 100644 --- a/src/IntegrationTests/Inheritance/QueryableInterfaceInheritanceIssue.cs +++ b/src/IntegrationTests/Inheritance/QueryableInterfaceInheritanceIssue.cs @@ -1,68 +1,68 @@ -using System.Collections.Generic; -using System.Data.Entity; -using System.Linq; -using AutoMapper.QueryableExtensions; +using System.Linq; +using System.Threading.Tasks; using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; using Shouldly; using Xunit; -namespace AutoMapper.IntegrationTests +namespace AutoMapper.IntegrationTests.Inheritance; + +public class QueryableInterfaceInheritanceIssue : AutoMapperSpecBase, IAsyncLifetime { - public class QueryableInterfaceInheritanceIssue : AutoMapperSpecBase + QueryableDto[] _result; + + public interface IBaseQueryableInterface { - QueryableDto[] _result; + string Id { get; set; } + } - public interface IBaseQueryableInterface - { - string Id { get; set; } - } + public interface IQueryableInterface : IBaseQueryableInterface + { + } - public interface IQueryableInterface : IBaseQueryableInterface - { - } + public class QueryableInterfaceImpl : IQueryableInterface + { + public string Id { get; set; } + } - public class QueryableInterfaceImpl : IQueryableInterface - { - public string Id { get; set; } - } + public class QueryableDto + { + public string Id { get; set; } + } - public class QueryableDto + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(ClientContext context) { - public string Id { get; set; } + context.Entities.AddRange(new[] { new QueryableInterfaceImpl { Id = "One" }, new QueryableInterfaceImpl { Id = "Two" }}); } + } - class Initializer : DropCreateDatabaseAlways - { - protected override void Seed(ClientContext context) - { - context.Entities.AddRange(new[] { new QueryableInterfaceImpl { Id = "One" }, new QueryableInterfaceImpl { Id = "Two" }}); - } - } + class ClientContext : LocalDbContext + { + public DbSet Entities { get; set; } + } - class ClientContext : DbContext - { - public ClientContext() - { - Database.SetInitializer(new Initializer()); - } - public DbSet Entities { get; set; } - } + [Fact] + public void QueryableShouldMapSpecifiedBaseInterfaceMember() + { + _result.FirstOrDefault(dto => dto.Id == "One").ShouldNotBeNull(); + _result.FirstOrDefault(dto => dto.Id == "Two").ShouldNotBeNull(); + } - protected override void Because_of() - { - using(var context = new ClientContext()) - { - _result = ProjectTo(context.Entities).ToArray(); - } - } + protected override MapperConfiguration CreateConfiguration() => new(cfg => cfg.CreateProjection()); + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); - [Fact] - public void QueryableShouldMapSpecifiedBaseInterfaceMember() + using (var context = new ClientContext()) { - _result.FirstOrDefault(dto => dto.Id == "One").ShouldNotBeNull(); - _result.FirstOrDefault(dto => dto.Id == "Two").ShouldNotBeNull(); + _result = ProjectTo(context.Entities).ToArray(); } - - protected override MapperConfiguration CreateConfiguration() => new(cfg => cfg.CreateProjection()); } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/LocalDbContext.cs b/src/IntegrationTests/LocalDbContext.cs new file mode 100644 index 0000000000..6dbadfac17 --- /dev/null +++ b/src/IntegrationTests/LocalDbContext.cs @@ -0,0 +1,23 @@ +using System.Globalization; +using Microsoft.EntityFrameworkCore; + +namespace AutoMapper.IntegrationTests; + +public abstract class LocalDbContext : DbContext +{ + private readonly string _localDbVersion = "mssqllocaldb"; + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + var baseConnectionString = @"Integrated Security=True; MultipleActiveResultSets=True;"; + + var connectionString = string.Format( + CultureInfo.InvariantCulture, + @"Data Source=(localdb)\{1};{0};Database={2}", + baseConnectionString, + _localDbVersion, + GetType().FullName); + + optionsBuilder.UseSqlServer(connectionString); + } +} \ No newline at end of file diff --git a/src/IntegrationTests/MaxDepth/MaxDepthWithCollections.cs b/src/IntegrationTests/MaxDepth/MaxDepthWithCollections.cs index c5c99f5fc8..3b5fa8517b 100644 --- a/src/IntegrationTests/MaxDepth/MaxDepthWithCollections.cs +++ b/src/IntegrationTests/MaxDepth/MaxDepthWithCollections.cs @@ -1,100 +1,101 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.Data.Entity; using System.Linq; -using AutoMapper.QueryableExtensions; +using System.Threading.Tasks; using AutoMapper.UnitTests; -using Xunit; +using Microsoft.EntityFrameworkCore; using Shouldly; +using Xunit; + +namespace AutoMapper.IntegrationTests.MaxDepth; -namespace AutoMapper.IntegrationTests.Net4 +public class MaxDepthWithCollections : AutoMapperSpecBase, IAsyncLifetime { - public class MaxDepthWithCollections : AutoMapperSpecBase + TrainingCourseDto _course; + + protected override MapperConfiguration CreateConfiguration() => new(cfg => { - TrainingCourseDto _course; + //cfg.AllowNullDestinationValues = false; + cfg.CreateProjection().MaxDepth(1); + cfg.CreateProjection(); + }); - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - //cfg.AllowNullDestinationValues = false; - cfg.CreateProjection().MaxDepth(1); - cfg.CreateProjection(); - }); + [Fact] + public void Should_project_with_MaxDepth() + { + _course.CourseName.ShouldBe("Course 1"); + var content = _course.Content[0]; + content.ContentName.ShouldBe("Content 1"); + content.Course.ShouldBeNull(); + } - protected override void Because_of() + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(ClientContext context) { - using(var context = new ClientContext()) - { - _course = ProjectTo(context.TrainingCourses).FirstOrDefault(n => n.CourseName == "Course 1"); - } + var course = new TrainingCourse { CourseName = "Course 1" }; + context.TrainingCourses.Add(course); + var content = new TrainingContent { ContentName = "Content 1", Course = course }; + context.TrainingContents.Add(content); + course.Content.Add(content); } + } - [Fact] - public void Should_project_with_MaxDepth() - { - _course.CourseName.ShouldBe("Course 1"); - var content = _course.Content[0]; - content.ContentName.ShouldBe("Content 1"); - content.Course.ShouldBeNull(); - } + class ClientContext : LocalDbContext + { + public DbSet TrainingCourses { get; set; } + public DbSet TrainingContents { get; set; } + } - class Initializer : DropCreateDatabaseAlways - { - protected override void Seed(ClientContext context) - { - var course = new TrainingCourse { CourseName = "Course 1" }; - context.TrainingCourses.Add(course); - var content = new TrainingContent { ContentName = "Content 1", Course = course }; - context.TrainingContents.Add(content); - course.Content.Add(content); - } - } + public class TrainingCourse + { + [Key] + public int CourseId { get; set; } - class ClientContext : DbContext - { - public ClientContext() - { - Database.SetInitializer(new Initializer()); - } - public DbSet TrainingCourses { get; set; } - public DbSet TrainingContents { get; set; } - } + public string CourseName { get; set; } - public class TrainingCourse - { - [Key] - public int CourseId { get; set; } + public virtual IList Content { get; set; } = new List(); + } - public string CourseName { get; set; } + public class TrainingContent + { + [Key] + public int ContentId { get; set; } - public virtual IList Content { get; set; } = new List(); - } + public string ContentName { get; set; } - public class TrainingContent - { - [Key] - public int ContentId { get; set; } + public virtual TrainingCourse Course { get; set; } + } - public string ContentName { get; set; } + public class TrainingCourseDto + { + public int CourseId { get; set; } - public virtual TrainingCourse Course { get; set; } - } + public string CourseName { get; set; } - public class TrainingCourseDto - { - public int CourseId { get; set; } + public virtual IList Content { get; set; } + } - public string CourseName { get; set; } + public class TrainingContentDto + { + public int ContentId { get; set; } - public virtual IList Content { get; set; } - } + public string ContentName { get; set; } - public class TrainingContentDto - { - public int ContentId { get; set; } + public TrainingCourseDto Course { get; set; } + } - public string ContentName { get; set; } + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); - public TrainingCourseDto Course { get; set; } + using (var context = new ClientContext()) + { + _course = ProjectTo(context.TrainingCourses).FirstOrDefault(n => n.CourseName == "Course 1"); } } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/MaxDepth/NavigationPropertySO.cs b/src/IntegrationTests/MaxDepth/NavigationPropertySO.cs index 7f65a99b7f..6e862213bd 100644 --- a/src/IntegrationTests/MaxDepth/NavigationPropertySO.cs +++ b/src/IntegrationTests/MaxDepth/NavigationPropertySO.cs @@ -1,109 +1,109 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -using System.Data.Entity; using System.Linq; +using System.Threading.Tasks; +using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; using Shouldly; using Xunit; -namespace AutoMapper.IntegrationTests.Net4 +namespace AutoMapper.IntegrationTests.MaxDepth; + +public class NavigationPropertySO : AutoMapperSpecBase, IAsyncLifetime { - using QueryableExtensions; - using UnitTests; + CustomerDTO _destination; - - public class NavigationPropertySO : AutoMapperSpecBase + public class Cust { - CustomerDTO _destination; - public class Cust - { + [Key] + public int CustomerID { get; set; } - [Key] - public int CustomerID { get; set; } + public string CustomerNumber { get; set; } + public bool Status { get; set; } + public virtual ICollection Customers { get; set; } + } - public string CustomerNumber { get; set; } - public bool Status { get; set; } - public virtual ICollection Customers { get; set; } - } + public class Customer + { + [Key] + public int Id { get; set; } + + [ForeignKey("Cust")] + public int CustomerId { get; set; } + public virtual Cust Cust { get; set; } + public bool Status { get; set; } + public string Name1 { get; set; } + } - public class Customer - { - [Key] - public int Id { get; set; } - - [ForeignKey("Cust")] - public int CustomerId { get; set; } - public virtual Cust Cust { get; set; } - public bool Status { get; set; } - public string Name1 { get; set; } - } + public class CustDTO + { + public int CustomerID { get; set; } + public string CustomerNumber { get; set; } + public bool Status { get; set; } - public class CustDTO - { - public int CustomerID { get; set; } - public string CustomerNumber { get; set; } - public bool Status { get; set; } + public virtual ICollection Customers { get; set; } + } - public virtual ICollection Customers { get; set; } - } + public class CustomerDTO + { + public int Id { get; set; } - public class CustomerDTO - { - public int Id { get; set; } + public int CustomerId { get; set; } + public virtual CustDTO Cust { get; set; } + public bool Status { get; set; } + public string Name1 { get; set; } + } - public int CustomerId { get; set; } - public virtual CustDTO Cust { get; set; } - public bool Status { get; set; } - public string Name1 { get; set; } - } + public class Context : LocalDbContext + { + public DbSet Customers { get; set; } + public DbSet Custs { get; set; } + } - public class Context : DbContext + public class DatabaseInitializer : CreateDatabaseIfNotExists + { + protected override void Seed(Context context) { - public Context() + var cust = new Cust { }; + context.Custs.Add(cust); + var customer = new Customer { - Database.SetInitializer(new DatabaseInitializer()); - } - - public DbSet Customers { get; set; } - public DbSet Custs { get; set; } + Name1 = "Bob", + CustomerId = 1, + Cust = cust, + }; + context.Customers.Add(customer); + cust.Customers.Add(customer); + base.Seed(context); } + } + + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection().MaxDepth(1); + cfg.CreateProjection(); + }); - public class DatabaseInitializer : CreateDatabaseIfNotExists + [Fact] + public void Can_map_with_projection() + { + using(var context = new Context()) { - protected override void Seed(Context context) - { - var cust = new Cust { CustomerID = 1 }; - context.Custs.Add(cust); - var customer = new Customer - { - Id = 1, - Name1 = "Bob", - CustomerId = 1, - Cust = cust, - }; - context.Customers.Add(customer); - cust.Customers.Add(customer); - base.Seed(context); - } + _destination = ProjectTo(context.Customers).Single(); + _destination.Id.ShouldBe(1); + _destination.Name1.SequenceEqual("Bob"); + _destination.Cust.CustomerID.ShouldBe(1); } + } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection().MaxDepth(1); - cfg.CreateProjection(); - }); + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); - [Fact] - public void Can_map_with_projection() - { - using(var context = new Context()) - { - _destination = ProjectTo(context.Customers).Single(); - _destination.Id.ShouldBe(1); - _destination.Name1.SequenceEqual("Bob"); - _destination.Cust.CustomerID.ShouldBe(1); - } - } + await initializer.Migrate(); } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/MaxDepth/NestedDtos.cs b/src/IntegrationTests/MaxDepth/NestedDtos.cs index 136bd59e06..a02c171b7b 100644 --- a/src/IntegrationTests/MaxDepth/NestedDtos.cs +++ b/src/IntegrationTests/MaxDepth/NestedDtos.cs @@ -1,95 +1,96 @@ -using System.ComponentModel.DataAnnotations; -using System.Data.Entity; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; using System.Linq; -using Xunit; -using Shouldly; -using AutoMapper.QueryableExtensions; +using System.Threading.Tasks; using AutoMapper.UnitTests; -using System.ComponentModel.DataAnnotations.Schema; -using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using Shouldly; +using Xunit; + +namespace AutoMapper.IntegrationTests.MaxDepth; -namespace AutoMapper.IntegrationTests.Net4 +public class NestedDtos : AutoMapperSpecBase, IAsyncLifetime { - public class NestedDtos : AutoMapperSpecBase + ArtDto _destination; + + public class Sem { - ArtDto _destination; + [Key] + public int Key { get; set; } + public string Name { get; set; } - public class Sem - { - [Key] - public int Key { get; set; } - public string Name { get; set; } + public virtual ICollection Arts { get; set; } + } - public virtual ICollection Arts { get; set; } - } + public class Art + { + [Key] + public int Key { get; set; } + public string AName { get; set; } - public class Art - { - [Key] - public int Key { get; set; } - public string AName { get; set; } + [ForeignKey("Sem")] + public int? SemKey { get; set; } + public virtual Sem Sem { get; set; } + } - [ForeignKey("Sem")] - public int? SemKey { get; set; } - public virtual Sem Sem { get; set; } - } + public class SemDto + { + public int Key { get; set; } + public string Name { get; set; } + } - public class SemDto - { - public int Key { get; set; } - public string Name { get; set; } - } + public class ArtDto + { + public int Key { get; set; } + public string AName { get; set; } - public class ArtDto - { - public int Key { get; set; } - public string AName { get; set; } + public SemDto Sem { get; set; } + } - public SemDto Sem { get; set; } - } + public class TestContext : LocalDbContext + { + public DbSet Arts { get; set; } + } - public class TestContext : DbContext + public class DatabaseInitializer : CreateDatabaseIfNotExists + { + protected override void Seed(TestContext context) { - public TestContext() - { - Database.SetInitializer(new DatabaseInitializer()); - } - public DbSet Arts { get; set; } - } + context.Arts.AddRange(new[] { + new Art { AName = "art1", Sem = new Sem { Name = "sem1" } }, + new Art { AName = "art2", Sem = new Sem { Name = "sem2" } }, + new Art { AName = "art3", Sem = new Sem { Name = "sem3" } }, + }); - public class DatabaseInitializer : CreateDatabaseIfNotExists - { - protected override void Seed(TestContext context) - { - context.Arts.AddRange(new[] { - new Art { AName = "art1", Sem = new Sem { Name = "sem1" } }, - new Art { AName = "art2", Sem = new Sem { Name = "sem2" } }, - new Art { AName = "art3", Sem = new Sem { Name = "sem3" } }, - }); - - base.Seed(context); - } + base.Seed(context); } + } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection().MaxDepth(1).ConstructUsing(s => new SemDto()); - cfg.CreateProjection().MaxDepth(1).ConstructUsing(s => new ArtDto()); - }); + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection().MaxDepth(1).ConstructUsing(s => new SemDto()); + cfg.CreateProjection().MaxDepth(1).ConstructUsing(s => new ArtDto()); + }); - protected override void Because_of() - { - using(var context = new TestContext()) - { - _destination = ProjectTo(context.Arts).FirstOrDefault(); - } - } + [Fact] + public void Should_project_nested_dto() + { + _destination.AName.ShouldBe("art1"); + _destination.Sem.Name.ShouldBe("sem1"); + } - [Fact] - public void Should_project_nested_dto() + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + + using (var context = new TestContext()) { - _destination.AName.ShouldBe("art1"); - _destination.Sem.Name.ShouldBe("sem1"); + _destination = ProjectTo(context.Arts).FirstOrDefault(); } } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/NullCheckCollections.cs b/src/IntegrationTests/NullCheckCollections.cs index e02c30320d..ab7f3d0c07 100644 --- a/src/IntegrationTests/NullCheckCollections.cs +++ b/src/IntegrationTests/NullCheckCollections.cs @@ -1,168 +1,190 @@ using System.ComponentModel.DataAnnotations; -using System.Data.Entity; +using Microsoft.EntityFrameworkCore; using System.Linq; using Shouldly; using Xunit; using System.ComponentModel.DataAnnotations.Schema; using System.Collections.Generic; +using System.Threading.Tasks; -namespace AutoMapper.IntegrationTests +namespace AutoMapper.IntegrationTests; + +using System; +using UnitTests; +public class NullCheckCollectionsFirstOrDefault : AutoMapperSpecBase, IAsyncLifetime { - using System; - using UnitTests; - public class NullCheckCollectionsFirstOrDefault : AutoMapperSpecBase + public class SourceType { - public class SourceType - { - public int Id { get; set; } - public ICollection Parameters { get; set; } = new List(); - } - public class Parameter - { - public int Id { get; set; } - public string Name { get; set; } - public int Value { get; set; } - } - public class DestinationType - { - public int? Index { get; set; } - } - class Initializer : DropCreateDatabaseAlways - { - protected override void Seed(TestContext context) => context.SourceTypes.Add(new SourceType { Parameters = { new Parameter { Name = "Index", Value = 101 } } }); - } - class TestContext : DbContext - { - protected override void OnModelCreating(DbModelBuilder modelBuilder) => Database.SetInitializer(new Initializer()); - public DbSet SourceTypes { get; set; } - } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - cfg.CreateProjection().ForMember(d => d.Index, o => o.MapFrom(source => source.Parameters.FirstOrDefault(p => p.Name == "Index").Value))); - [Fact] - public void Should_project_ok() - { - using (var context = new TestContext()) - { - ProjectTo(context.SourceTypes).Single().Index.ShouldBe(101); - } - } + public int Id { get; set; } + public ICollection Parameters { get; set; } = new List(); } - public class NullChildItemTest : AutoMapperSpecBase + public class Parameter { - protected override MapperConfiguration CreateConfiguration() => new(cfg => cfg.CreateProjection()); - public class TestContext : DbContext - { - public TestContext() : base() => Database.SetInitializer(new DatabaseInitializer()); - public DbSet Parents { get; set; } - } - public class DatabaseInitializer : DropCreateDatabaseAlways - { - protected override void Seed(TestContext testContext) - { - testContext.Parents.Add(new Parent { Value = 5 }); - base.Seed(testContext); - } - } - [Fact] - public void Should_project_null_value() - { - using (var context = new TestContext()) - { - var query = ProjectTo(context.Parents); - var projected = query.Single(); - projected.Value.ShouldBe(5); - projected.ChildValue.ShouldBeNull(); - projected.ChildGrandChildValue.ShouldBeNull(); - projected.Nephews.ShouldBeEmpty(); - } - } - public class ParentDto - { - public int? Value { get; set; } - public int? ChildValue { get; set; } - public int? ChildGrandChildValue { get; set; } - public List Nephews { get; set; } - } - public class Parent - { - public int Id { get; set; } - public int Value { get; set; } - public Child Child { get; set; } - public List Nephews { get; set; } - } - public class Child - { - public int Id { get; set; } - public int Value { get; set; } - public GrandChild GrandChild { get; set; } - } - public class GrandChild - { - public int Value { get; set; } - } + public int Id { get; set; } + public string Name { get; set; } + public int Value { get; set; } } - public class NullCheckCollections : AutoMapperSpecBase + public class DestinationType { - public class Student - { - [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public int Id { get; set; } - public string Name { get; set; } - public virtual ICollection ScoreRecords { get; set; } - } - public class ScoreRecord + public int? Index { get; set; } + } + class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(TestContext context) => context.SourceTypes.Add(new SourceType { Parameters = { new Parameter { Name = "Index", Value = 101 } } }); + } + class TestContext : LocalDbContext + { + public DbSet SourceTypes { get; set; } + } + protected override MapperConfiguration CreateConfiguration() => new(cfg => + cfg.CreateProjection().ForMember(d => d.Index, o => o.MapFrom(source => source.Parameters.FirstOrDefault(p => p.Name == "Index").Value))); + [Fact] + public void Should_project_ok() + { + using (var context = new TestContext()) { - [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public int Id { get; set; } - public int StudentId { get; set; } - public virtual Student Student { get; set; } - public string Subject { get; set; } - public int Score { get; set; } + ProjectTo(context.SourceTypes).Single().Index.ShouldBe(101); } - public class ScoreModel + } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; +} +public class NullChildItemTest : AutoMapperSpecBase, IAsyncLifetime +{ + protected override MapperConfiguration CreateConfiguration() => new(cfg => cfg.CreateProjection()); + public class TestContext : LocalDbContext + { + public DbSet Parents { get; set; } + } + public class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(TestContext testContext) { - public int? MinScore { get; set; } - public int? MaxScore { get; set; } + testContext.Parents.Add(new Parent { Value = 5 }); + base.Seed(testContext); } - public class StudentViewModel + } + [Fact] + public void Should_project_null_value() + { + using (var context = new TestContext()) { - public int Id { get; set; } - public string Name { get; set; } - public ScoreModel Score { get; set; } + var query = ProjectTo(context.Parents); + var projected = query.Single(); + projected.Value.ShouldBe(5); + projected.ChildValue.ShouldBeNull(); + projected.ChildGrandChildValue.ShouldBeNull(); + projected.Nephews.ShouldBeEmpty(); } + } + public class ParentDto + { + public int? Value { get; set; } + public int? ChildValue { get; set; } + public int? ChildGrandChildValue { get; set; } + public List Nephews { get; set; } + } + public class Parent + { + public int Id { get; set; } + public int Value { get; set; } + public Child Child { get; set; } + public List Nephews { get; set; } + } + public class Child + { + public int Id { get; set; } + public int Value { get; set; } + public GrandChild GrandChild { get; set; } + } + public class GrandChild + { + public int Id { get; set; } + public int Value { get; set; } + } - public class Context : DbContext - { - public Context() - { - Database.SetInitializer(new DatabaseInitializer()); - } - public DbSet Students { get; set; } - } + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; +} +public class NullCheckCollections : AutoMapperSpecBase, IAsyncLifetime +{ + public class Student + { + [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; set; } + public string Name { get; set; } + public virtual ICollection ScoreRecords { get; set; } + } + public class ScoreRecord + { + [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; set; } + public int StudentId { get; set; } + public virtual Student Student { get; set; } + public string Subject { get; set; } + public int Score { get; set; } + } + public class ScoreModel + { + public int? MinScore { get; set; } + public int? MaxScore { get; set; } + } + public class StudentViewModel + { + public int Id { get; set; } + public string Name { get; set; } + public ScoreModel Score { get; set; } + } + + public class Context : LocalDbContext + { + public DbSet Students { get; set; } + } - public class DatabaseInitializer : DropCreateDatabaseAlways + public class DatabaseInitializer : DropCreateDatabaseAlways + { + protected override void Seed(Context context) { - protected override void Seed(Context context) - { - context.Students.Add(new Student{ Name = "Bob" }); - } + context.Students.Add(new Student{ Name = "Bob" }); } + } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection().ForMember(d => d.Score, opts => opts.MapFrom(m => m.ScoreRecords)); - cfg.CreateProjection, ScoreModel>() - .ForMember(d => d.MinScore, opts => opts.MapFrom(m => m.Min(s => s.Score))) - .ForMember(d => d.MaxScore, opts => opts.MapFrom(m => m.Max(s => s.Score))); - }); + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection().ForMember(d => d.Score, opts => opts.MapFrom(m => m.ScoreRecords)); + cfg.CreateProjection, ScoreModel>() + .ForMember(d => d.MinScore, opts => opts.MapFrom(m => m.Min(s => s.Score))) + .ForMember(d => d.MaxScore, opts => opts.MapFrom(m => m.Max(s => s.Score))); + }); - [Fact] - public void Can_map_with_projection() + [Fact] + public void Can_map_with_projection() + { + using (var context = new Context()) { - using (var context = new Context()) - { - ProjectTo(context.Students).Single().Name.ShouldBe("Bob"); - } + ProjectTo(context.Students).Single().Name.ShouldBe("Bob"); } } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/NullSubstitute.cs b/src/IntegrationTests/NullSubstitute.cs index 2e9d399f34..4054756b3f 100644 --- a/src/IntegrationTests/NullSubstitute.cs +++ b/src/IntegrationTests/NullSubstitute.cs @@ -1,158 +1,177 @@ using System.ComponentModel.DataAnnotations; -using System.Data.Entity; +using Microsoft.EntityFrameworkCore; using System.Linq; +using System.Threading.Tasks; using Shouldly; using Xunit; -namespace AutoMapper.IntegrationTests -{ - using UnitTests; +namespace AutoMapper.IntegrationTests; + +using UnitTests; - public class NullSubstitute : AutoMapperSpecBase +public class NullSubstitute : AutoMapperSpecBase, IAsyncLifetime +{ + public class Customer { - public class Customer - { - [Key] - public int Id { get; set; } + [Key] + public int Id { get; set; } - public double? Value { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - } + public double? Value { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + } - public class CustomerViewModel - { - public double Value { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - } + public class CustomerViewModel + { + public double Value { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + } - public class Context : DbContext + public class Context : LocalDbContext + { + public DbSet Customers { get; set; } + } + + public class DatabaseInitializer : CreateDatabaseIfNotExists + { + protected override void Seed(Context context) { - public Context() + context.Customers.Add(new Customer { - Database.SetInitializer(new DatabaseInitializer()); - } + FirstName = "Bob", + LastName = "Smith", + }); - public DbSet Customers { get; set; } + base.Seed(context); } + } - public class DatabaseInitializer : CreateDatabaseIfNotExists + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection().ForMember(d => d.Value, o => o.NullSubstitute(5)); + }); + + [Fact] + public void Can_map_with_projection() + { + using (var context = new Context()) { - protected override void Seed(Context context) - { - context.Customers.Add(new Customer - { - Id = 1, - FirstName = "Bob", - LastName = "Smith", - }); - - base.Seed(context); - } + ProjectTo(context.Customers).First().Value.ShouldBe(5); } + } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection().ForMember(d => d.Value, o => o.NullSubstitute(5)); - }); + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); - [Fact] - public void Can_map_with_projection() - { - using (var context = new Context()) - { - ProjectTo(context.Customers).First().Value.ShouldBe(5); - } - } + await initializer.Migrate(); } - public class NullSubstituteWithStrings : AutoMapperSpecBase + + public Task DisposeAsync() => Task.CompletedTask; +} +public class NullSubstituteWithStrings : AutoMapperSpecBase, IAsyncLifetime +{ + public class Customer { - public class Customer - { - public int Id { get; set; } - public string Value { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - } - public class CustomerViewModel - { - public string Value { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - } - public class Context : DbContext - { - public Context() => Database.SetInitializer(new DatabaseInitializer()); - public DbSet Customers { get; set; } - } - public class DatabaseInitializer : CreateDatabaseIfNotExists - { - protected override void Seed(Context context) - { - context.Customers.Add(new Customer { Id = 1, FirstName = "Bob", LastName = "Smith" }); - base.Seed(context); - } - } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - cfg.CreateProjection().ForMember(d => d.Value, o => o.NullSubstitute("5"))); - [Fact] - public void Can_map_with_projection() - { - using (var context = new Context()) - { - ProjectTo(context.Customers).First().Value.ShouldBe("5"); - } - } + public int Id { get; set; } + public string Value { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } } - public class NullSubstituteWithEntity : AutoMapperSpecBase + public class CustomerViewModel { - class Customer - { - public int Id { get; set; } - public Value Value { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - } - class Value - { - public int Id { get; set; } - } - class CustomerViewModel - { - public ValueViewModel Value { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - } - class ValueViewModel + public string Value { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + } + public class Context : LocalDbContext + { + public DbSet Customers { get; set; } + } + public class DatabaseInitializer : CreateDatabaseIfNotExists + { + protected override void Seed(Context context) { - public int Id { get; set; } + context.Customers.Add(new Customer { FirstName = "Bob", LastName = "Smith" }); + base.Seed(context); } - class Context : DbContext + } + protected override MapperConfiguration CreateConfiguration() => new(cfg => + cfg.CreateProjection().ForMember(d => d.Value, o => o.NullSubstitute("5"))); + [Fact] + public void Can_map_with_projection() + { + using (var context = new Context()) { - public Context() => Database.SetInitializer(new DatabaseInitializer()); - public DbSet Customers { get; set; } + ProjectTo(context.Customers).First().Value.ShouldBe("5"); } - class DatabaseInitializer : CreateDatabaseIfNotExists + } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; +} +public class NullSubstituteWithEntity : AutoMapperSpecBase, IAsyncLifetime +{ + class Customer + { + public int Id { get; set; } + public Value Value { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + } + class Value + { + public int Id { get; set; } + } + class CustomerViewModel + { + public ValueViewModel Value { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + } + class ValueViewModel + { + public int Id { get; set; } + } + class Context : LocalDbContext + { + public DbSet Customers { get; set; } + } + class DatabaseInitializer : CreateDatabaseIfNotExists + { + protected override void Seed(Context context) { - protected override void Seed(Context context) - { - context.Customers.Add(new Customer { Id = 1, FirstName = "Bob", LastName = "Smith" }); - base.Seed(context); - } + context.Customers.Add(new Customer { FirstName = "Bob", LastName = "Smith" }); + base.Seed(context); } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection().ForMember(d => d.Value, o => o.NullSubstitute(new Value())); - cfg.CreateProjection(); - }); - [Fact] - public void Can_map_with_projection() + } + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection().ForMember(d => d.Value, o => o.NullSubstitute(new Value())); + cfg.CreateProjection(); + }); + [Fact] + public void Can_map_with_projection() + { + using (var context = new Context()) { - using (var context = new Context()) - { - ProjectTo(context.Customers).First().Value.ShouldBeNull(); - } + ProjectTo(context.Customers).First().Value.ShouldBeNull(); } } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/ParameterizedQueries.cs b/src/IntegrationTests/ParameterizedQueries.cs index 4118e22c57..97438ecc46 100644 --- a/src/IntegrationTests/ParameterizedQueries.cs +++ b/src/IntegrationTests/ParameterizedQueries.cs @@ -1,109 +1,110 @@ -using System; -using System.Collections.Generic; -using System.Data.Entity; +using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; -using AutoMapper.QueryableExtensions; using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; using Shouldly; using Xunit; -namespace AutoMapper.IntegrationTests.Parameterization +namespace AutoMapper.IntegrationTests; + +public class ParameterizedQueries : AutoMapperSpecBase, IAsyncLifetime { - public class ParameterizedQueries : AutoMapperSpecBase + public class Entity { - public class Entity - { - public int Id { get; set; } - public string Value { get; set; } - } - - public class EntityDto - { - public int Id { get; set; } - public string Value { get; set; } - public string UserName { get; set; } - } + public int Id { get; set; } + public string Value { get; set; } + } - private class ClientContext : DbContext - { - static ClientContext() - { - Database.SetInitializer(new DatabaseInitializer()); - } + public class EntityDto + { + public int Id { get; set; } + public string Value { get; set; } + public string UserName { get; set; } + } - public DbSet Entities { get; set; } - } + private class ClientContext : LocalDbContext + { + public DbSet Entities { get; set; } + } - private class DatabaseInitializer : CreateDatabaseIfNotExists + private class DatabaseInitializer : CreateDatabaseIfNotExists + { + protected override void Seed(ClientContext context) { - protected override void Seed(ClientContext context) + context.Entities.AddRange(new[] { - context.Entities.AddRange(new[] - { - new Entity {Value = "Value1"}, - new Entity {Value = "Value2"} - }); - base.Seed(context); - } + new Entity {Value = "Value1"}, + new Entity {Value = "Value2"} + }); + base.Seed(context); } + } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - string username = null; - cfg.CreateProjection() - .ForMember(d => d.UserName, opt => opt.MapFrom(s => username)); - }); + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + string username = null; + cfg.CreateProjection() + .ForMember(d => d.UserName, opt => opt.MapFrom(s => username)); + }); - [Fact] - public async Task Should_parameterize_value() + [Fact] + public async Task Should_parameterize_value() + { + List dtos; + string username; + using (var db = new ClientContext()) { - List dtos; - string username; - using (var db = new ClientContext()) - { - username = "Mary"; - var query = ProjectTo(db.Entities, new { username }); - dtos = await query.ToListAsync(); - var constantVisitor = new ConstantVisitor(); - constantVisitor.Visit(query.Expression); - constantVisitor.HasConstant.ShouldBeFalse(); - dtos.All(dto => dto.UserName == username).ShouldBeTrue(); + username = "Mary"; + var query = ProjectTo(db.Entities, new { username }); + dtos = await query.ToListAsync(); + var constantVisitor = new ConstantVisitor(); + constantVisitor.Visit(query.Expression); + constantVisitor.HasConstant.ShouldBeFalse(); + dtos.All(dto => dto.UserName == username).ShouldBeTrue(); - username = "Joe"; - query = ProjectTo(db.Entities, new Dictionary { { "username", username }}); - dtos = await query.ToListAsync(); - constantVisitor = new ConstantVisitor(); - constantVisitor.Visit(query.Expression); - constantVisitor.HasConstant.ShouldBeTrue(); - dtos.All(dto => dto.UserName == username).ShouldBeTrue(); + username = "Joe"; + query = ProjectTo(db.Entities, new Dictionary { { "username", username }}); + dtos = await query.ToListAsync(); + constantVisitor = new ConstantVisitor(); + constantVisitor.Visit(query.Expression); + constantVisitor.HasConstant.ShouldBeTrue(); + dtos.All(dto => dto.UserName == username).ShouldBeTrue(); - username = "Jane"; - query = db.Entities.Select(e => new EntityDto - { - Id = e.Id, - Value = e.Value, - UserName = username - }); - dtos = await query.ToListAsync(); - dtos.All(dto => dto.UserName == username).ShouldBeTrue(); - constantVisitor = new ConstantVisitor(); - constantVisitor.Visit(query.Expression); - constantVisitor.HasConstant.ShouldBeFalse(); - } + username = "Jane"; + query = db.Entities.Select(e => new EntityDto + { + Id = e.Id, + Value = e.Value, + UserName = username + }); + dtos = await query.ToListAsync(); + dtos.All(dto => dto.UserName == username).ShouldBeTrue(); + constantVisitor = new ConstantVisitor(); + constantVisitor.Visit(query.Expression); + constantVisitor.HasConstant.ShouldBeFalse(); } + } - private class ConstantVisitor : ExpressionVisitor - { - public bool HasConstant { get; private set; } + private class ConstantVisitor : ExpressionVisitor + { + public bool HasConstant { get; private set; } - protected override Expression VisitConstant(ConstantExpression node) - { - if (node.Type == typeof(string)) - HasConstant = true; - return base.VisitConstant(node); - } + protected override Expression VisitConstant(ConstantExpression node) + { + if (node.Type == typeof(string)) + HasConstant = true; + return base.VisitConstant(node); } } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } \ No newline at end of file diff --git a/src/IntegrationTests/ProjectionOrderTest.cs b/src/IntegrationTests/ProjectionOrderTest.cs index f19fc66328..329703c38d 100644 --- a/src/IntegrationTests/ProjectionOrderTest.cs +++ b/src/IntegrationTests/ProjectionOrderTest.cs @@ -1,78 +1,87 @@ using System; using System.Collections.Generic; -using System.Data.Entity; using System.Linq; -using AutoMapper.QueryableExtensions; +using System.Threading.Tasks; using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; using Xunit; -namespace AutoMapper.IntegrationTests.ProjectionOrder +namespace AutoMapper.IntegrationTests; + +public class ProjectionOrderTest : AutoMapperSpecBase, IAsyncLifetime { - public class ProjectionOrderTest : AutoMapperSpecBase + public class Destination { - public class Destination - { - public int Count { get; set; } - public DateTime Date { get; set; } - } - - public class ChildDestination - { - public string String { get; set; } - } + public int Count { get; set; } + public DateTime Date { get; set; } + } - public abstract class BaseEntity - { - public int Id { get; set; } - } + public class ChildDestination + { + public string String { get; set; } + } + public abstract class BaseEntity + { + public int Id { get; set; } + } - public class Source1 : BaseEntity - { - public DateTime Date { get; set; } - public virtual List Items { get; set; } - } - public class Source2 : BaseEntity - { - public virtual List Items { get; set; } - } + public class Source1 : BaseEntity + { + public DateTime Date { get; set; } + public virtual List Items { get; set; } + } - public class ChildSource : BaseEntity - { - public string String { get; set; } - } + public class Source2 : BaseEntity + { + public virtual List Items { get; set; } + } - private class ClientContext : DbContext - { - static ClientContext() - { - Database.SetInitializer(new DropCreateDatabaseAlways()); - } + public class ChildSource : BaseEntity + { + public string String { get; set; } + } - public DbSet Source1 { get; set; } + private class ClientContext : LocalDbContext + { + public DbSet Source1 { get; set; } - public DbSet Source2 { get; set; } - } + public DbSet Source2 { get; set; } + } - protected override MapperConfiguration CreateConfiguration() => new(cfg => - { - cfg.CreateProjection() - .ForMember(dest => dest.Count, opt => opt.MapFrom(src => src.Items.Count())) - .ForMember(dest => dest.Date, opt => opt.MapFrom(src => src.Date)); + protected override MapperConfiguration CreateConfiguration() => new(cfg => + { + cfg.CreateProjection() + .ForMember(dest => dest.Count, opt => opt.MapFrom(src => src.Items.Count())) + .ForMember(dest => dest.Date, opt => opt.MapFrom(src => src.Date)); - cfg.CreateProjection() - .ForMember(dest => dest.Count, opt => opt.MapFrom(src => src.Items.Count())) - .ForMember(dest => dest.Date, opt => opt.MapFrom(src => DateTime.MinValue)); - }); + cfg.CreateProjection() + .ForMember(dest => dest.Count, opt => opt.MapFrom(src => src.Items.Count())) + .ForMember(dest => dest.Date, opt => opt.MapFrom(src => DateTime.MinValue)); + }); - [Fact] - public void Should_Not_Throw_NotSupportedException_On_Union() + [Fact] + public void Should_Not_Throw_NotSupportedException_On_Union() + { + using (var context = new ClientContext()) { - using (var context = new ClientContext()) - { - ProjectTo(context.Source1).Union(ProjectTo(context.Source2)).ToString(); - } + ProjectTo(context.Source1).Union(ProjectTo(context.Source2)).ToString(); } } -} + + class DatabaseInitializer : DropCreateDatabaseAlways + { + + } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; + +} \ No newline at end of file diff --git a/src/IntegrationTests/ValueTransformerTests.cs b/src/IntegrationTests/ValueTransformerTests.cs index 7ea4dd4a95..573a011a7d 100644 --- a/src/IntegrationTests/ValueTransformerTests.cs +++ b/src/IntegrationTests/ValueTransformerTests.cs @@ -1,16 +1,15 @@ using System.ComponentModel.DataAnnotations; -using System.Data.Entity; using System.Threading.Tasks; -using AutoMapper.QueryableExtensions; using AutoMapper.UnitTests; +using Microsoft.EntityFrameworkCore; using Shouldly; using Xunit; -namespace AutoMapper.IntegrationTests.ValueTransformers +namespace AutoMapper.IntegrationTests { namespace ValueTransformerTests { - public class BasicTransforming : AutoMapperSpecBase + public class BasicTransforming : AutoMapperSpecBase, IAsyncLifetime { public class Source { @@ -24,14 +23,8 @@ public class Dest public string Value { get; set; } } - public class Context : DbContext + public class Context : LocalDbContext { - public Context() - : base() - { - Database.SetInitializer(new DatabaseInitializer()); - } - public DbSet Sources { get; set; } } @@ -61,9 +54,18 @@ public async Task Should_transform_value() dest.Value.ShouldBe("Jimmy is straight up dope"); } } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } - public class StackingTransformers : AutoMapperSpecBase + public class StackingTransformers : AutoMapperSpecBase, IAsyncLifetime { public class Source { @@ -77,14 +79,8 @@ public class Dest public string Value { get; set; } } - public class Context : DbContext + public class Context : LocalDbContext { - public Context() - : base() - { - Database.SetInitializer(new DatabaseInitializer()); - } - public DbSet Sources { get; set; } } @@ -115,9 +111,18 @@ public async Task Should_stack_transformers_in_order() dest.Value.ShouldBe("Jimmy is straight up dope! No joke!"); } } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } - public class DifferentProfiles : AutoMapperSpecBase + public class DifferentProfiles : AutoMapperSpecBase, IAsyncLifetime { public class Source { @@ -138,14 +143,8 @@ public class Dest cfg.CreateProfile("Other", p => p.ValueTransformers.Add(dest => dest + "! No joke!")); }); - public class Context : DbContext + public class Context : LocalDbContext { - public Context() - : base() - { - Database.SetInitializer(new DatabaseInitializer()); - } - public DbSet Sources { get; set; } } @@ -169,9 +168,18 @@ public async Task Should_not_apply_other_transform() dest.Value.ShouldBe("Jimmy is straight up dope"); } } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } - public class StackingRootConfigAndProfileTransform : AutoMapperSpecBase + public class StackingRootConfigAndProfileTransform : AutoMapperSpecBase, IAsyncLifetime { public class Source { @@ -185,14 +193,8 @@ public class Dest public string Value { get; set; } } - public class Context : DbContext + public class Context : LocalDbContext { - public Context() - : base() - { - Database.SetInitializer(new DatabaseInitializer()); - } - public DbSet Sources { get; set; } } @@ -225,9 +227,18 @@ public async Task ShouldApplyProfileFirstThenRoot() dest.Value.ShouldBe("Jimmy is straight up dope! No joke!"); } } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } - public class TransformingValueTypes : AutoMapperSpecBase + public class TransformingValueTypes : AutoMapperSpecBase, IAsyncLifetime { public class Source { @@ -241,14 +252,8 @@ public class Dest public int Value { get; set; } } - public class Context : DbContext + public class Context : LocalDbContext { - public Context() - : base() - { - Database.SetInitializer(new DatabaseInitializer()); - } - public DbSet Sources { get; set; } } @@ -281,9 +286,18 @@ public async Task ShouldApplyProfileFirstThenRoot() dest.Value.ShouldBe((5 + 3) * 2); } } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } - public class StackingRootAndProfileAndMemberConfig : AutoMapperSpecBase + public class StackingRootAndProfileAndMemberConfig : AutoMapperSpecBase, IAsyncLifetime { public class Source { @@ -297,14 +311,8 @@ public class Dest public string Value { get; set; } } - public class Context : DbContext + public class Context : LocalDbContext { - public Context() - : base() - { - Database.SetInitializer(new DatabaseInitializer()); - } - public DbSet Sources { get; set; } } @@ -339,9 +347,18 @@ public async Task ShouldApplyTypeMapThenProfileThenRoot() dest.Value.ShouldBe("Jimmy, for real, is straight up dope! No joke!"); } } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } - public class StackingTypeMapAndRootAndProfileAndMemberConfig : AutoMapperSpecBase + public class StackingTypeMapAndRootAndProfileAndMemberConfig : AutoMapperSpecBase, IAsyncLifetime { public class Source { @@ -355,14 +372,8 @@ public class Dest public string Value { get; set; } } - public class Context : DbContext + public class Context : LocalDbContext { - public Context() - : base() - { - Database.SetInitializer(new DatabaseInitializer()); - } - public DbSet Sources { get; set; } } @@ -397,6 +408,15 @@ public async Task ShouldApplyTypeMapThenProfileThenRoot() dest.Value.ShouldBe("Jimmy, seriously, for real, is straight up dope! No joke!"); } } + + public async Task InitializeAsync() + { + var initializer = new DatabaseInitializer(); + + await initializer.Migrate(); + } + + public Task DisposeAsync() => Task.CompletedTask; } diff --git a/src/UnitTests/AutoMapperSpecBase.cs b/src/UnitTests/AutoMapperSpecBase.cs index c90aacf64e..1e6eab90bb 100644 --- a/src/UnitTests/AutoMapperSpecBase.cs +++ b/src/UnitTests/AutoMapperSpecBase.cs @@ -7,124 +7,123 @@ using System.Linq.Expressions; using AutoMapper.Configuration; -namespace AutoMapper.UnitTests +namespace AutoMapper.UnitTests; + +/// +/// Ignore this member for validation and skip during mapping +/// +[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] +public class IgnoreMapAttribute : Attribute { - /// - /// Ignore this member for validation and skip during mapping - /// - [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] - public class IgnoreMapAttribute : Attribute - { - } - static class Utils +} +static class Utils +{ + public static TypeMap FindTypeMapFor(this IConfigurationProvider configurationProvider) => configurationProvider.Internal().FindTypeMapFor(); + public static IReadOnlyCollection GetAllTypeMaps(this IConfigurationProvider configurationProvider) => configurationProvider.Internal().GetAllTypeMaps(); + public static TypeMap ResolveTypeMap(this IConfigurationProvider configurationProvider, Type sourceType, Type destinationType) => configurationProvider.Internal().ResolveTypeMap(sourceType, destinationType); + public static void ForAllMaps(this IMapperConfigurationExpression configurationProvider, Action configuration) => configurationProvider.Internal().ForAllMaps(configuration); + public static void ForAllPropertyMaps(this IMapperConfigurationExpression configurationProvider, Func condition, Action memberOptions) => + configurationProvider.Internal().ForAllPropertyMaps(condition, memberOptions); + public static void AddIgnoreMapAttribute(this IMapperConfigurationExpression configuration) { - public static TypeMap FindTypeMapFor(this IConfigurationProvider configurationProvider) => configurationProvider.Internal().FindTypeMapFor(); - public static IReadOnlyCollection GetAllTypeMaps(this IConfigurationProvider configurationProvider) => configurationProvider.Internal().GetAllTypeMaps(); - public static TypeMap ResolveTypeMap(this IConfigurationProvider configurationProvider, Type sourceType, Type destinationType) => configurationProvider.Internal().ResolveTypeMap(sourceType, destinationType); - public static void ForAllMaps(this IMapperConfigurationExpression configurationProvider, Action configuration) => configurationProvider.Internal().ForAllMaps(configuration); - public static void ForAllPropertyMaps(this IMapperConfigurationExpression configurationProvider, Func condition, Action memberOptions) => - configurationProvider.Internal().ForAllPropertyMaps(condition, memberOptions); - public static void AddIgnoreMapAttribute(this IMapperConfigurationExpression configuration) + configuration.ForAllMaps((typeMap, mapExpression) => mapExpression.ForAllMembers(memberOptions => { - configuration.ForAllMaps((typeMap, mapExpression) => mapExpression.ForAllMembers(memberOptions => + if (memberOptions.DestinationMember.Has()) { - if (memberOptions.DestinationMember.Has()) - { - memberOptions.Ignore(); - } - })); - configuration.ForAllPropertyMaps(propertyMap => propertyMap.SourceMember?.Has() == true, - (_, memberOptions) => memberOptions.Ignore()); - } + memberOptions.Ignore(); + } + })); + configuration.ForAllPropertyMaps(propertyMap => propertyMap.SourceMember?.Has() == true, + (_, memberOptions) => memberOptions.Ignore()); } +} - public abstract class AutoMapperSpecBase : NonValidatingSpecBase +public abstract class AutoMapperSpecBase : NonValidatingSpecBase +{ + protected override void OnConfig(MapperConfiguration mapperConfiguration) => mapperConfiguration.AssertConfigurationIsValid(); +} + +public abstract class NonValidatingSpecBase : SpecBase +{ + private IMapper _mapper; + protected abstract MapperConfiguration CreateConfiguration(); + protected IGlobalConfiguration Configuration => Mapper.ConfigurationProvider.Internal(); + protected IMapper Mapper => _mapper ??= CreateMapper(); + IMapper CreateMapper() { - protected override void OnConfig(MapperConfiguration mapperConfiguration) => mapperConfiguration.AssertConfigurationIsValid(); + var config = CreateConfiguration(); + OnConfig(config); + return config.CreateMapper(); } + protected virtual void OnConfig(MapperConfiguration mapperConfiguration) { } + protected TDestination Map(object source) => Mapper.Map(source); + protected TypeMap FindTypeMapFor() => Configuration.FindTypeMapFor(); + protected void AssertConfigurationIsValid() => Configuration.AssertConfigurationIsValid(); + protected void AssertConfigurationIsValid() => Configuration.AssertConfigurationIsValid(Configuration.FindTypeMapFor()); + protected void AssertConfigurationIsValid(Type sourceType, Type destinationType) => Configuration.AssertConfigurationIsValid(Configuration.FindTypeMapFor(sourceType, destinationType)); + public void AssertConfigurationIsValid(string profileName) => Configuration.AssertConfigurationIsValid(profileName); + public void AssertConfigurationIsValid() where TProfile : Profile, new() => Configuration.AssertConfigurationIsValid(); + protected IQueryable ProjectTo(IQueryable source, object parameters = null, params Expression>[] membersToExpand) => + Mapper.ProjectTo(source, parameters, membersToExpand); + protected IQueryable ProjectTo(IQueryable source, IDictionary parameters, params string[] membersToExpand) => + Mapper.ProjectTo(source, parameters, membersToExpand); + public IEnumerable GetProfiles() => Configuration.Profiles; +} - public abstract class NonValidatingSpecBase : SpecBase +public abstract class SpecBaseBase +{ + protected virtual void MainSetup() { - private IMapper _mapper; - protected abstract MapperConfiguration CreateConfiguration(); - protected IGlobalConfiguration Configuration => Mapper.ConfigurationProvider.Internal(); - protected IMapper Mapper => _mapper ??= CreateMapper(); - IMapper CreateMapper() - { - var config = CreateConfiguration(); - OnConfig(config); - return config.CreateMapper(); - } - protected virtual void OnConfig(MapperConfiguration mapperConfiguration) { } - protected TDestination Map(object source) => Mapper.Map(source); - protected TypeMap FindTypeMapFor() => Configuration.FindTypeMapFor(); - protected void AssertConfigurationIsValid() => Configuration.AssertConfigurationIsValid(); - protected void AssertConfigurationIsValid() => Configuration.AssertConfigurationIsValid(Configuration.FindTypeMapFor()); - protected void AssertConfigurationIsValid(Type sourceType, Type destinationType) => Configuration.AssertConfigurationIsValid(Configuration.FindTypeMapFor(sourceType, destinationType)); - public void AssertConfigurationIsValid(string profileName) => Configuration.AssertConfigurationIsValid(profileName); - public void AssertConfigurationIsValid() where TProfile : Profile, new() => Configuration.AssertConfigurationIsValid(); - protected IQueryable ProjectTo(IQueryable source, object parameters = null, params Expression>[] membersToExpand) => - Mapper.ProjectTo(source, parameters, membersToExpand); - protected IQueryable ProjectTo(IQueryable source, IDictionary parameters, params string[] membersToExpand) => - Mapper.ProjectTo(source, parameters, membersToExpand); - public IEnumerable GetProfiles() => Configuration.Profiles; + Establish_context(); + Because_of(); } - public abstract class SpecBaseBase + protected virtual void MainTeardown() { - protected virtual void MainSetup() - { - Establish_context(); - Because_of(); - } - - protected virtual void MainTeardown() - { - Cleanup(); - } + Cleanup(); + } - protected virtual void Establish_context() - { - } + protected virtual void Establish_context() + { + } - protected virtual void Because_of() - { - } + protected virtual void Because_of() + { + } - protected virtual void Cleanup() - { - } + protected virtual void Cleanup() + { } - public abstract class SpecBase : SpecBaseBase, IDisposable +} +public abstract class SpecBase : SpecBaseBase, IDisposable +{ + protected SpecBase() { - protected SpecBase() - { - Establish_context(); - Because_of(); - } + Establish_context(); + Because_of(); + } - public void Dispose() - { - Cleanup(); - } + public void Dispose() + { + Cleanup(); } - class FirstOrDefaultCounter : ExpressionVisitor +} +class FirstOrDefaultCounter : ExpressionVisitor +{ + public int Count; + protected override Expression VisitMethodCall(MethodCallExpression node) { - public int Count; - protected override Expression VisitMethodCall(MethodCallExpression node) - { - if (node.Method.Name == "FirstOrDefault") - { - Count++; - } - return base.VisitMethodCall(node); - } - public static void Assert(IQueryable queryable, int count) => Assert(queryable.Expression, count); - public static void Assert(Expression expression, int count) + if (node.Method.Name == "FirstOrDefault") { - var firstOrDefault = new FirstOrDefaultCounter(); - firstOrDefault.Visit(expression); - firstOrDefault.Count.ShouldBe(count); + Count++; } + return base.VisitMethodCall(node); + } + public static void Assert(IQueryable queryable, int count) => Assert(queryable.Expression, count); + public static void Assert(Expression expression, int count) + { + var firstOrDefault = new FirstOrDefaultCounter(); + firstOrDefault.Visit(expression); + firstOrDefault.Count.ShouldBe(count); } } \ No newline at end of file