diff --git a/test/EFCore.Relational.Specification.Tests/TPTTableSplittingTestBase.cs b/test/EFCore.Relational.Specification.Tests/TPTTableSplittingTestBase.cs index c000fddc14a..b6304801f27 100644 --- a/test/EFCore.Relational.Specification.Tests/TPTTableSplittingTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/TPTTableSplittingTestBase.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Threading.Tasks; using Microsoft.EntityFrameworkCore.TestModels.TransportationModel; using Xunit.Abstractions; @@ -14,12 +15,13 @@ protected TPTTableSplittingTestBase(ITestOutputHelper testOutputHelper) { } - public override void Can_use_optional_dependents_with_shared_concurrency_tokens() + public override Task Can_use_optional_dependents_with_shared_concurrency_tokens() { // TODO: Issue #22060 + return Task.CompletedTask; } - protected override string DatabaseName { get; } = "TPTTableSplittingTest"; + protected override string StoreName { get; } = "TPTTableSplittingTest"; protected override void OnModelCreating(ModelBuilder modelBuilder) { diff --git a/test/EFCore.Relational.Specification.Tests/TableSplittingTestBase.cs b/test/EFCore.Relational.Specification.Tests/TableSplittingTestBase.cs index 2b44edd2a88..e92bdf21c8c 100644 --- a/test/EFCore.Relational.Specification.Tests/TableSplittingTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/TableSplittingTestBase.cs @@ -3,122 +3,113 @@ using System; using System.Linq; -using Microsoft.EntityFrameworkCore.Diagnostics; +using System.Threading.Tasks; using Microsoft.EntityFrameworkCore.TestModels.TransportationModel; using Microsoft.EntityFrameworkCore.TestUtilities; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using Xunit; using Xunit.Abstractions; // ReSharper disable InconsistentNaming namespace Microsoft.EntityFrameworkCore { - public abstract class TableSplittingTestBase + public abstract class TableSplittingTestBase : NonSharedModelTestBase { protected TableSplittingTestBase(ITestOutputHelper testOutputHelper) { - TestSqlLoggerFactory = (TestSqlLoggerFactory)TestStoreFactory.CreateListLoggerFactory(_ => true); //TestSqlLoggerFactory.SetTestOutputHelper(testOutputHelper); } [ConditionalFact] - public virtual void Can_update_just_dependents() + public virtual async Task Can_update_just_dependents() { - using (CreateTestStore(OnModelCreating)) + await InitializeAsync(OnModelCreating); + + Operator firstOperator; + Engine firstEngine; + using (var context = CreateContext()) { - Operator firstOperator; - Engine firstEngine; - using (var context = CreateContext()) - { - firstOperator = context.Set().OrderBy(o => o.VehicleName).First(); - firstOperator.Name += "1"; - firstEngine = context.Set().OrderBy(o => o.VehicleName).First(); - firstEngine.Description += "1"; + firstOperator = context.Set().OrderBy(o => o.VehicleName).First(); + firstOperator.Name += "1"; + firstEngine = context.Set().OrderBy(o => o.VehicleName).First(); + firstEngine.Description += "1"; - context.SaveChanges(); + context.SaveChanges(); - Assert.Empty(context.ChangeTracker.Entries().Where(e => e.State != EntityState.Unchanged)); - } + Assert.Empty(context.ChangeTracker.Entries().Where(e => e.State != EntityState.Unchanged)); + } - using (var context = CreateContext()) - { - Assert.Equal(firstOperator.Name, context.Set().OrderBy(o => o.VehicleName).First().Name); - Assert.Equal(firstEngine.Description, context.Set().OrderBy(o => o.VehicleName).First().Description); - } + using (var context = CreateContext()) + { + Assert.Equal(firstOperator.Name, context.Set().OrderBy(o => o.VehicleName).First().Name); + Assert.Equal(firstEngine.Description, context.Set().OrderBy(o => o.VehicleName).First().Description); } } [ConditionalFact] - public virtual void Can_query_shared() + public virtual async Task Can_query_shared() { - using (CreateTestStore(OnModelCreating)) - { - using var context = CreateContext(); - Assert.Equal(5, context.Set().ToList().Count); - } + await InitializeAsync(OnModelCreating); + + using var context = CreateContext(); + Assert.Equal(5, context.Set().ToList().Count); } [ConditionalFact] - public virtual void Can_query_shared_nonhierarchy() + public virtual async Task Can_query_shared_nonhierarchy() { - using (CreateTestStore( + await InitializeAsync( modelBuilder => { OnModelCreating(modelBuilder); modelBuilder.Ignore(); - })) - { - using var context = CreateContext(); - Assert.Equal(5, context.Set().ToList().Count); - } + }); + + using var context = CreateContext(); + Assert.Equal(5, context.Set().ToList().Count); } [ConditionalFact] - public virtual void Can_query_shared_nonhierarchy_with_nonshared_dependent() + public virtual async Task Can_query_shared_nonhierarchy_with_nonshared_dependent() { - using (CreateTestStore( + await InitializeAsync( modelBuilder => { OnModelCreating(modelBuilder); modelBuilder.Ignore(); modelBuilder.Entity().ToTable("OperatorDetails"); - })) - { - using var context = CreateContext(); - Assert.Equal(5, context.Set().ToList().Count); - } + }); + + using var context = CreateContext(); + Assert.Equal(5, context.Set().ToList().Count); } [ConditionalFact] - public virtual void Can_query_shared_derived_hierarchy() + public virtual async Task Can_query_shared_derived_hierarchy() { - using (CreateTestStore(OnModelCreating)) - { - using var context = CreateContext(); - Assert.Equal(2, context.Set().ToList().Count); - } + await InitializeAsync(OnModelCreating); + + using var context = CreateContext(); + Assert.Equal(2, context.Set().ToList().Count); } [ConditionalFact] - public virtual void Can_query_shared_derived_nonhierarchy() + public virtual async Task Can_query_shared_derived_nonhierarchy() { - using (CreateTestStore( + await InitializeAsync( modelBuilder => { OnModelCreating(modelBuilder); modelBuilder.Ignore(); - })) - { - using var context = CreateContext(); - Assert.Equal(2, context.Set().ToList().Count); - } + }); + + using var context = CreateContext(); + Assert.Equal(2, context.Set().ToList().Count); } [ConditionalFact] - public virtual void Can_query_shared_derived_nonhierarchy_all_required() + public virtual async Task Can_query_shared_derived_nonhierarchy_all_required() { - using (CreateTestStore( + await InitializeAsync( modelBuilder => { OnModelCreating(modelBuilder); @@ -129,23 +120,22 @@ public virtual void Can_query_shared_derived_nonhierarchy_all_required() eb.Property(t => t.Capacity).IsRequired(); eb.Property(t => t.FuelType).IsRequired(); }); - })) - { - using var context = CreateContext(); - Assert.Equal(2, context.Set().ToList().Count); - } + }); + + using var context = CreateContext(); + Assert.Equal(2, context.Set().ToList().Count); } [ConditionalFact] - public virtual void Can_use_with_redundant_relationships() + public virtual Task Can_use_with_redundant_relationships() { - Test_roundtrip(OnModelCreating); + return Test_roundtrip(OnModelCreating); } [ConditionalFact] - public virtual void Can_use_with_chained_relationships() + public virtual Task Can_use_with_chained_relationships() { - Test_roundtrip( + return Test_roundtrip( modelBuilder => { OnModelCreating(modelBuilder); @@ -154,9 +144,9 @@ public virtual void Can_use_with_chained_relationships() } [ConditionalFact] - public virtual void Can_use_with_fanned_relationships() + public virtual Task Can_use_with_fanned_relationships() { - Test_roundtrip( + return Test_roundtrip( modelBuilder => { OnModelCreating(modelBuilder); @@ -166,9 +156,9 @@ public virtual void Can_use_with_fanned_relationships() } [ConditionalFact] - public virtual void Can_share_required_columns() + public virtual async Task Can_share_required_columns() { - using (CreateTestStore( + await InitializeAsync( modelBuilder => { OnModelCreating(modelBuilder); @@ -184,37 +174,36 @@ public virtual void Can_share_required_columns() }); modelBuilder.Entity().HasOne(e => e.FuelTank).WithOne().HasForeignKey(e => e.VehicleName); modelBuilder.Entity().Ignore(f => f.Engine); - }, seed: false)) + }, seed: false); + + using (var context = CreateContext()) { - using (var context = CreateContext()) - { - var scooterEntry = context.Add( - new PoweredVehicle - { - Name = "Electric scooter", - SeatingCapacity = 1, - Engine = new Engine(), - Operator = new Operator { Name = "Kai Saunders" } - }); + var scooterEntry = context.Add( + new PoweredVehicle + { + Name = "Electric scooter", + SeatingCapacity = 1, + Engine = new Engine(), + Operator = new Operator { Name = "Kai Saunders" } + }); - scooterEntry.Reference(v => v.Engine).TargetEntry.Property("SeatingCapacity").CurrentValue = 1; + scooterEntry.Reference(v => v.Engine).TargetEntry.Property("SeatingCapacity").CurrentValue = 1; - context.SaveChanges(); - } + context.SaveChanges(); + } - using (var context = CreateContext()) - { - var scooter = context.Set().Include(v => v.Engine).Single(v => v.Name == "Electric scooter"); + using (var context = CreateContext()) + { + var scooter = context.Set().Include(v => v.Engine).Single(v => v.Name == "Electric scooter"); - Assert.Equal(scooter.SeatingCapacity, context.Entry(scooter.Engine).Property("SeatingCapacity").CurrentValue); - } + Assert.Equal(scooter.SeatingCapacity, context.Entry(scooter.Engine).Property("SeatingCapacity").CurrentValue); } } [ConditionalFact] - public virtual void Can_use_optional_dependents_with_shared_concurrency_tokens() + public virtual async Task Can_use_optional_dependents_with_shared_concurrency_tokens() { - using (CreateTestStore( + await InitializeAsync( modelBuilder => { OnModelCreating(modelBuilder); @@ -230,181 +219,177 @@ public virtual void Can_use_optional_dependents_with_shared_concurrency_tokens() }); modelBuilder.Entity().HasOne(e => e.FuelTank).WithOne().HasForeignKey(e => e.VehicleName); modelBuilder.Entity().Ignore(f => f.Engine); - }, seed: false)) + }, seed: false); + + using (var context = CreateContext()) { - using (var context = CreateContext()) - { - var scooterEntry = context.Add( - new PoweredVehicle - { - Name = "Electric scooter", - SeatingCapacity = 1, - Operator = new Operator { Name = "Kai Saunders" } - }); + var scooterEntry = context.Add( + new PoweredVehicle + { + Name = "Electric scooter", + SeatingCapacity = 1, + Operator = new Operator { Name = "Kai Saunders" } + }); - context.SaveChanges(); - } + context.SaveChanges(); + } - using (var context = CreateContext()) - { - var scooter = context.Set().Include(v => v.Engine).Single(v => v.Name == "Electric scooter"); + using (var context = CreateContext()) + { + var scooter = context.Set().Include(v => v.Engine).Single(v => v.Name == "Electric scooter"); - Assert.Equal(1, scooter.SeatingCapacity); + Assert.Equal(1, scooter.SeatingCapacity); - scooter.Engine = new Engine(); + scooter.Engine = new Engine(); - var engineCapacityEntry = context.Entry(scooter.Engine).Property("SeatingCapacity"); + var engineCapacityEntry = context.Entry(scooter.Engine).Property("SeatingCapacity"); - Assert.Equal(0, engineCapacityEntry.OriginalValue); + Assert.Equal(0, engineCapacityEntry.OriginalValue); - context.SaveChanges(); + context.SaveChanges(); - Assert.Equal(0, engineCapacityEntry.OriginalValue); - Assert.Equal(0, engineCapacityEntry.CurrentValue); - } + Assert.Equal(0, engineCapacityEntry.OriginalValue); + Assert.Equal(0, engineCapacityEntry.CurrentValue); + } - using (var context = CreateContext()) - { - var scooter = context.Set().Include(v => v.Engine).Single(v => v.Name == "Electric scooter"); + using (var context = CreateContext()) + { + var scooter = context.Set().Include(v => v.Engine).Single(v => v.Name == "Electric scooter"); - Assert.Equal(scooter.SeatingCapacity, context.Entry(scooter.Engine).Property("SeatingCapacity").CurrentValue); + Assert.Equal(scooter.SeatingCapacity, context.Entry(scooter.Engine).Property("SeatingCapacity").CurrentValue); - scooter.SeatingCapacity = 2; - context.SaveChanges(); - } + scooter.SeatingCapacity = 2; + context.SaveChanges(); + } - using (var context = CreateContext()) - { - var scooter = context.Set().Include(v => v.Engine).Single(v => v.Name == "Electric scooter"); + using (var context = CreateContext()) + { + var scooter = context.Set().Include(v => v.Engine).Single(v => v.Name == "Electric scooter"); - Assert.Equal(2, scooter.SeatingCapacity); - Assert.Equal(2, context.Entry(scooter.Engine).Property("SeatingCapacity").CurrentValue); - } + Assert.Equal(2, scooter.SeatingCapacity); + Assert.Equal(2, context.Entry(scooter.Engine).Property("SeatingCapacity").CurrentValue); } } - protected void Test_roundtrip(Action onModelCreating) + protected async Task Test_roundtrip(Action onModelCreating) { - using (CreateTestStore(onModelCreating)) - { - using var context = CreateContext(); - context.AssertSeeded(); - } + await InitializeAsync(onModelCreating); + + using var context = CreateContext(); + context.AssertSeeded(); } [ConditionalFact] - public virtual void Can_manipulate_entities_sharing_row_independently() + public virtual async Task Can_manipulate_entities_sharing_row_independently() { - using (CreateTestStore( + await InitializeAsync( modelBuilder => { OnModelCreating(modelBuilder); modelBuilder.Entity().HasOne(e => e.FuelTank).WithOne().HasForeignKey(e => e.VehicleName); modelBuilder.Entity(eb => eb.Ignore(e => e.Engine)); - })) + }); + + PoweredVehicle streetcar; + using (var context = CreateContext()) { - PoweredVehicle streetcar; - using (var context = CreateContext()) - { - streetcar = context.Set().Include(v => v.Engine) - .Single(v => v.Name == "1984 California Car"); + streetcar = context.Set().Include(v => v.Engine) + .Single(v => v.Name == "1984 California Car"); - Assert.Null(streetcar.Engine); + Assert.Null(streetcar.Engine); - streetcar.Engine = new Engine { Description = "Streetcar engine" }; + streetcar.Engine = new Engine { Description = "Streetcar engine" }; - context.SaveChanges(); - } + context.SaveChanges(); + } - using (var context = CreateContext()) - { - var streetcarFromStore = context.Set().Include(v => v.Engine).AsNoTracking() - .Single(v => v.Name == "1984 California Car"); + using (var context = CreateContext()) + { + var streetcarFromStore = context.Set().Include(v => v.Engine).AsNoTracking() + .Single(v => v.Name == "1984 California Car"); - Assert.Equal("Streetcar engine", streetcarFromStore.Engine.Description); + Assert.Equal("Streetcar engine", streetcarFromStore.Engine.Description); - streetcarFromStore.Engine.Description = "Line"; + streetcarFromStore.Engine.Description = "Line"; - context.Update(streetcarFromStore); - context.SaveChanges(); - } + context.Update(streetcarFromStore); + context.SaveChanges(); + } - using (var context = CreateContext()) - { - var streetcarFromStore = context.Set().Include(v => v.Engine) - .Single(v => v.Name == "1984 California Car"); + using (var context = CreateContext()) + { + var streetcarFromStore = context.Set().Include(v => v.Engine) + .Single(v => v.Name == "1984 California Car"); - Assert.Equal("Line", streetcarFromStore.Engine.Description); + Assert.Equal("Line", streetcarFromStore.Engine.Description); - streetcarFromStore.SeatingCapacity = 40; - streetcarFromStore.Engine.Description = "Streetcar engine"; + streetcarFromStore.SeatingCapacity = 40; + streetcarFromStore.Engine.Description = "Streetcar engine"; - context.SaveChanges(); - } + context.SaveChanges(); + } - using (var context = CreateContext()) - { - var streetcarFromStore = context.Set().Include(v => v.Engine).AsNoTracking() - .Single(v => v.Name == "1984 California Car"); + using (var context = CreateContext()) + { + var streetcarFromStore = context.Set().Include(v => v.Engine).AsNoTracking() + .Single(v => v.Name == "1984 California Car"); - Assert.Equal(40, streetcarFromStore.SeatingCapacity); - Assert.Equal("Streetcar engine", streetcarFromStore.Engine.Description); + Assert.Equal(40, streetcarFromStore.SeatingCapacity); + Assert.Equal("Streetcar engine", streetcarFromStore.Engine.Description); - context.Remove(streetcarFromStore.Engine); + context.Remove(streetcarFromStore.Engine); - context.SaveChanges(); - } + context.SaveChanges(); + } - using (var context = CreateContext()) - { - var streetcarFromStore = context.Set().AsNoTracking() - .Include(v => v.Engine).Include(v => v.Operator) - .Single(v => v.Name == "1984 California Car"); + using (var context = CreateContext()) + { + var streetcarFromStore = context.Set().AsNoTracking() + .Include(v => v.Engine).Include(v => v.Operator) + .Single(v => v.Name == "1984 California Car"); - Assert.Null(streetcarFromStore.Engine); + Assert.Null(streetcarFromStore.Engine); - context.Remove(streetcarFromStore); + context.Remove(streetcarFromStore); - context.SaveChanges(); - } + context.SaveChanges(); + } - using (var context = CreateContext()) - { - Assert.Null(context.Set().AsNoTracking().SingleOrDefault(v => v.Name == "1984 California Car")); - Assert.Null(context.Set().AsNoTracking().SingleOrDefault(e => e.VehicleName == "1984 California Car")); - } + using (var context = CreateContext()) + { + Assert.Null(context.Set().AsNoTracking().SingleOrDefault(v => v.Name == "1984 California Car")); + Assert.Null(context.Set().AsNoTracking().SingleOrDefault(e => e.VehicleName == "1984 California Car")); } } [ConditionalFact] - public virtual void Can_insert_dependent_with_just_one_parent() + public virtual async Task Can_insert_dependent_with_just_one_parent() { - using (CreateTestStore(OnModelCreating)) - { - using var context = CreateContext(); - context.Add( - new PoweredVehicle - { - Name = "Fuel transport", - SeatingCapacity = 1, - Operator = new LicensedOperator { Name = "Jack Jackson", LicenseType = "Class A CDC" } - }); - context.Add( - new FuelTank - { - Capacity = "10000 l", - FuelType = "Gas", - VehicleName = "Fuel transport" - }); + await InitializeAsync(OnModelCreating); - context.SaveChanges(); - } + using var context = CreateContext(); + context.Add( + new PoweredVehicle + { + Name = "Fuel transport", + SeatingCapacity = 1, + Operator = new LicensedOperator { Name = "Jack Jackson", LicenseType = "Class A CDC" } + }); + context.Add( + new FuelTank + { + Capacity = "10000 l", + FuelType = "Gas", + VehicleName = "Fuel transport" + }); + + context.SaveChanges(); } [ConditionalFact] - public virtual void Can_change_dependent_instance_non_derived() + public virtual async Task Can_change_dependent_instance_non_derived() { - using (CreateTestStore( + await InitializeAsync( modelBuilder => { OnModelCreating(modelBuilder); @@ -420,37 +405,36 @@ public virtual void Can_change_dependent_instance_non_derived() }); modelBuilder.Ignore(); modelBuilder.Ignore(); - })) + }); + + using (var context = CreateContext()) { - using (var context = CreateContext()) - { - var bike = context.Vehicles.Include(v => v.Operator).Single(v => v.Name == "Trek Pro Fit Madone 6 Series"); + var bike = context.Vehicles.Include(v => v.Operator).Single(v => v.Name == "Trek Pro Fit Madone 6 Series"); - bike.Operator = new Operator { Name = "Chris Horner" }; + bike.Operator = new Operator { Name = "Chris Horner" }; - context.ChangeTracker.DetectChanges(); + context.ChangeTracker.DetectChanges(); - bike.Operator = new LicensedOperator { Name = "repairman", LicenseType = "Repair" }; + bike.Operator = new LicensedOperator { Name = "repairman", LicenseType = "Repair" }; - TestSqlLoggerFactory.Clear(); - context.SaveChanges(); + TestSqlLoggerFactory.Clear(); + context.SaveChanges(); - Assert.Empty(context.ChangeTracker.Entries().Where(e => e.State != EntityState.Unchanged)); - } + Assert.Empty(context.ChangeTracker.Entries().Where(e => e.State != EntityState.Unchanged)); + } - using (var context = CreateContext()) - { - var bike = context.Vehicles.Include(v => v.Operator).Single(v => v.Name == "Trek Pro Fit Madone 6 Series"); - Assert.Equal("repairman", bike.Operator.Name); - Assert.Equal("Repair", ((LicensedOperator)bike.Operator).LicenseType); - } + using (var context = CreateContext()) + { + var bike = context.Vehicles.Include(v => v.Operator).Single(v => v.Name == "Trek Pro Fit Madone 6 Series"); + Assert.Equal("repairman", bike.Operator.Name); + Assert.Equal("Repair", ((LicensedOperator)bike.Operator).LicenseType); } } [ConditionalFact] - public virtual void Can_change_principal_instance_non_derived() + public virtual async Task Can_change_principal_instance_non_derived() { - using (CreateTestStore( + await InitializeAsync( modelBuilder => { OnModelCreating(modelBuilder); @@ -466,42 +450,41 @@ public virtual void Can_change_principal_instance_non_derived() }); modelBuilder.Ignore(); modelBuilder.Ignore(); - })) + }); + + using (var context = CreateContext()) { - using (var context = CreateContext()) - { - var bike = context.Vehicles.Single(v => v.Name == "Trek Pro Fit Madone 6 Series"); + var bike = context.Vehicles.Single(v => v.Name == "Trek Pro Fit Madone 6 Series"); - var newBike = new Vehicle - { - Name = "Trek Pro Fit Madone 6 Series", - Operator = bike.Operator, - SeatingCapacity = 2 - }; + var newBike = new Vehicle + { + Name = "Trek Pro Fit Madone 6 Series", + Operator = bike.Operator, + SeatingCapacity = 2 + }; - context.Remove(bike); - context.Add(newBike); + context.Remove(bike); + context.Add(newBike); - TestSqlLoggerFactory.Clear(); - context.SaveChanges(); + TestSqlLoggerFactory.Clear(); + context.SaveChanges(); - Assert.Empty(context.ChangeTracker.Entries().Where(e => e.State != EntityState.Unchanged)); - } + Assert.Empty(context.ChangeTracker.Entries().Where(e => e.State != EntityState.Unchanged)); + } - using (var context = CreateContext()) - { - var bike = context.Vehicles.Include(v => v.Operator).Single(v => v.Name == "Trek Pro Fit Madone 6 Series"); + using (var context = CreateContext()) + { + var bike = context.Vehicles.Include(v => v.Operator).Single(v => v.Name == "Trek Pro Fit Madone 6 Series"); - Assert.Equal(2, bike.SeatingCapacity); - Assert.NotNull(bike.Operator); - } + Assert.Equal(2, bike.SeatingCapacity); + Assert.NotNull(bike.Operator); } } [ConditionalFact] - public virtual void Can_change_principal_and_dependent_instance_non_derived() + public virtual async Task Can_change_principal_and_dependent_instance_non_derived() { - using (CreateTestStore( + await InitializeAsync( modelBuilder => { OnModelCreating(modelBuilder); @@ -517,43 +500,41 @@ public virtual void Can_change_principal_and_dependent_instance_non_derived() }); modelBuilder.Ignore(); modelBuilder.Ignore(); - })) + }); + + using (var context = CreateContext()) { - using (var context = CreateContext()) - { - var bike = context.Vehicles.Include(v => v.Operator).Single(v => v.Name == "Trek Pro Fit Madone 6 Series"); + var bike = context.Vehicles.Include(v => v.Operator).Single(v => v.Name == "Trek Pro Fit Madone 6 Series"); - var newBike = new Vehicle - { - Name = "Trek Pro Fit Madone 6 Series", - Operator = new LicensedOperator { Name = "repairman", LicenseType = "Repair" }, - SeatingCapacity = 2 - }; + var newBike = new Vehicle + { + Name = "Trek Pro Fit Madone 6 Series", + Operator = new LicensedOperator { Name = "repairman", LicenseType = "Repair" }, + SeatingCapacity = 2 + }; - context.Remove(bike); - context.Add(newBike); + context.Remove(bike); + context.Add(newBike); - TestSqlLoggerFactory.Clear(); - context.SaveChanges(); + TestSqlLoggerFactory.Clear(); + context.SaveChanges(); - Assert.Empty(context.ChangeTracker.Entries().Where(e => e.State != EntityState.Unchanged)); - } + Assert.Empty(context.ChangeTracker.Entries().Where(e => e.State != EntityState.Unchanged)); + } - using (var context = CreateContext()) - { - var bike = context.Vehicles.Include(v => v.Operator).Single(v => v.Name == "Trek Pro Fit Madone 6 Series"); - Assert.Equal(2, bike.SeatingCapacity); - Assert.Equal("repairman", bike.Operator.Name); - Assert.Equal("Repair", ((LicensedOperator)bike.Operator).LicenseType); - } + using (var context = CreateContext()) + { + var bike = context.Vehicles.Include(v => v.Operator).Single(v => v.Name == "Trek Pro Fit Madone 6 Series"); + Assert.Equal(2, bike.SeatingCapacity); + Assert.Equal("repairman", bike.Operator.Name); + Assert.Equal("Repair", ((LicensedOperator)bike.Operator).LicenseType); } } - protected virtual string DatabaseName { get; } = "TableSplittingTest"; - protected TestStore TestStore { get; set; } - protected abstract ITestStoreFactory TestStoreFactory { get; } - protected IServiceProvider ServiceProvider { get; set; } - protected TestSqlLoggerFactory TestSqlLoggerFactory { get; } + protected override string StoreName { get; } = "TableSplittingTest"; + protected TestSqlLoggerFactory TestSqlLoggerFactory + => (TestSqlLoggerFactory)ListLoggerFactory; + protected ContextFactory ContextFactory { get; private set; } protected void AssertSql(params string[] expected) => TestSqlLoggerFactory.AssertBaseline(expected); @@ -576,42 +557,20 @@ protected virtual void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity().ToTable("Vehicles"); } - protected TestStore CreateTestStore(Action onModelCreating, bool seed = true) + protected async Task InitializeAsync(Action onModelCreating, bool seed = true) { - TestStore = TestStoreFactory.Create(DatabaseName); - - ServiceProvider = TestStoreFactory.AddProviderServices(new ServiceCollection()) - .AddSingleton(TestModelSource.GetFactory(onModelCreating)) - .AddSingleton(TestSqlLoggerFactory) - .BuildServiceProvider(validateScopes: true); - - TestStore.Initialize( - ServiceProvider, CreateContext, c => - { - if (seed) - { - ((TransportationContext)c).Seed(); - } - }); - - TestSqlLoggerFactory.Clear(); - - return TestStore; + ContextFactory = await InitializeAsync( + onModelCreating, shouldLogCategory: _ => true, seed: seed ? c => c.Seed() : null); } - protected virtual DbContextOptionsBuilder AddOptions(DbContextOptionsBuilder builder) - => builder - .EnableSensitiveDataLogging() - .ConfigureWarnings( - b => b.Default(WarningBehavior.Throw) - .Log(CoreEventId.SensitiveDataLoggingEnabledWarning) - .Log(CoreEventId.PossibleUnintendedReferenceComparisonWarning)); - protected virtual TransportationContext CreateContext() + => ContextFactory.CreateContext(); + + public override void Dispose() { - var options = AddOptions(TestStore.AddProviderOptions(new DbContextOptionsBuilder())) - .UseInternalServiceProvider(ServiceProvider).Options; - return new TransportationContext(options); + base.Dispose(); + + ContextFactory = null; } } } diff --git a/test/EFCore.Specification.Tests/ComplianceTestBase.cs b/test/EFCore.Specification.Tests/ComplianceTestBase.cs index 2d16395dc3b..3064709360d 100644 --- a/test/EFCore.Specification.Tests/ComplianceTestBase.cs +++ b/test/EFCore.Specification.Tests/ComplianceTestBase.cs @@ -26,6 +26,7 @@ public virtual void All_test_bases_must_be_implemented() var nonImplementedBases = (from baseType in GetBaseTestClasses() where !IgnoredTestBases.Contains(baseType) + && baseType != typeof(NonSharedModelTestBase) && !concreteTests.Any(c => Implements(c, baseType)) select baseType.FullName) .ToList(); diff --git a/test/EFCore.Specification.Tests/NonSharedModelTestBase.cs b/test/EFCore.Specification.Tests/NonSharedModelTestBase.cs new file mode 100644 index 00000000000..c95fa44e9c7 --- /dev/null +++ b/test/EFCore.Specification.Tests/NonSharedModelTestBase.cs @@ -0,0 +1,184 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Xunit; + +// ReSharper disable VirtualMemberCallInConstructor +namespace Microsoft.EntityFrameworkCore +{ + public abstract class NonSharedModelTestBase : IDisposable, IAsyncLifetime + { + protected abstract string StoreName { get; } + protected abstract ITestStoreFactory TestStoreFactory { get; } + + private ServiceProvider _serviceProvider; + protected IServiceProvider ServiceProvider + => _serviceProvider ?? throw new InvalidOperationException( + $"You must call `await {nameof(InitializeAsync)}(\"DatabaseName\");` at the beggining of the test."); + + private TestStore _testStore; + protected TestStore TestStore + => _testStore ?? throw new InvalidOperationException( + $"You must call `await {nameof(InitializeAsync)}(\"DatabaseName\");` at the beggining of the test."); + + private ListLoggerFactory _listLoggerFactory; + protected ListLoggerFactory ListLoggerFactory + => _listLoggerFactory ??= (ListLoggerFactory)ServiceProvider.GetRequiredService(); + + public virtual Task InitializeAsync() => Task.CompletedTask; + + protected virtual ContextFactory Initialize( + Action onModelCreating = null, + Action onConfiguring = null, + Action addServices = null, + Action seed = null, + Func shouldLogCategory = null, + Func createTestStore = null, + bool usePooling = true) + where TContext : DbContext + { + var contextFactory = Initialize( + onModelCreating, onConfiguring, addServices, shouldLogCategory, createTestStore, usePooling); + + TestStore.Initialize(_serviceProvider, contextFactory.CreateContext, seed == null ? null : c => seed((TContext)c)); + + ListLoggerFactory.Clear(); + + return contextFactory; + } + + protected virtual Task> InitializeAsync( + Action onModelCreating = null, + Action onConfiguring = null, + Action addServices = null, + Action seed = null, + Func shouldLogCategory = null, + Func createTestStore = null, + bool usePooling = true) + where TContext : DbContext + { + var contextFactory = Initialize( + onModelCreating, onConfiguring, addServices, shouldLogCategory, createTestStore, usePooling); + + TestStore.Initialize(_serviceProvider, contextFactory.CreateContext, seed == null ? null : c => seed((TContext)c)); + + ListLoggerFactory.Clear(); + + return Task.FromResult(contextFactory); + } + + private ContextFactory Initialize( + Action onModelCreating, + Action onConfiguring, + Action addServices, + Func shouldLogCategory, + Func createTestStore, + bool usePooling) + where TContext : DbContext + { + _testStore = createTestStore?.Invoke() ?? CreateTestStore(); + + shouldLogCategory ??= _ => false; + var services = TestStoreFactory.AddProviderServices(new ServiceCollection()) + .AddSingleton(TestStoreFactory.CreateListLoggerFactory(shouldLogCategory)); + + if (onModelCreating != null) + { + services = services.AddSingleton(TestModelSource.GetFactory(onModelCreating)); + } + + if (addServices != null) + { + addServices(services); + } + + services = usePooling + ? services.AddDbContextPool(typeof(TContext), (s, b) => ConfigureOptions(s, b, onConfiguring)) + : services.AddDbContext( + typeof(TContext), + (s, b) => ConfigureOptions(s, b, onConfiguring), + ServiceLifetime.Transient, + ServiceLifetime.Singleton); + + _serviceProvider = services.BuildServiceProvider(validateScopes: true); + + var contextFactory = new ContextFactory(_serviceProvider, usePooling, _testStore); + return contextFactory; + } + + private DbContextOptionsBuilder ConfigureOptions( + IServiceProvider serviceProvider, + DbContextOptionsBuilder optionsBuilder, + Action onConfiguring) + { + optionsBuilder = AddOptions(TestStore.AddProviderOptions(optionsBuilder)) + .UseInternalServiceProvider(serviceProvider); + onConfiguring?.Invoke(optionsBuilder); + return optionsBuilder; + } + + protected virtual DbContextOptionsBuilder AddOptions(DbContextOptionsBuilder builder) + => builder + .EnableSensitiveDataLogging() + .ConfigureWarnings( + b => b.Default(WarningBehavior.Throw) + .Log(CoreEventId.SensitiveDataLoggingEnabledWarning) + .Log(CoreEventId.PossibleUnintendedReferenceComparisonWarning)); + + protected virtual TestStore CreateTestStore() + => TestStoreFactory.Create(StoreName); + + // Called after DisposeAsync + public virtual void Dispose() + { + } + + public virtual async Task DisposeAsync() + { + if (_testStore != null) + { + await _testStore.DisposeAsync(); + _testStore = null; + } + + _serviceProvider?.Dispose(); + _serviceProvider = null; + + _listLoggerFactory = null; + } + + protected class ContextFactory + where TContext : DbContext + { + public ContextFactory(IServiceProvider serviceProvider, bool usePooling, TestStore testStore) + { + ServiceProvider = serviceProvider; + UsePooling = usePooling; + if (usePooling) + { + ContextPool ??= (IDbContextPool)ServiceProvider + .GetRequiredService(typeof(IDbContextPool<>).MakeGenericType(typeof(TContext))); + } + + TestStore = testStore; + } + + public IServiceProvider ServiceProvider { get; } + protected virtual bool UsePooling { get; } + private IDbContextPool ContextPool { get; } + public TestStore TestStore { get; } + + public virtual TContext CreateContext() + => UsePooling + ? (TContext)new DbContextLease(ContextPool, standalone: true).Context + : (TContext)ServiceProvider.GetRequiredService(typeof(TContext)); + } + } +} diff --git a/test/EFCore.Specification.Tests/Query/NorthwindIncludeQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/NorthwindIncludeQueryTestBase.cs index 9cdc9e3b396..35407851b4a 100644 --- a/test/EFCore.Specification.Tests/Query/NorthwindIncludeQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/NorthwindIncludeQueryTestBase.cs @@ -1683,6 +1683,20 @@ where c.CustomerID.StartsWith("F") entryCount: 26); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Repro9735(bool async) + { + return AssertQuery( + async, + ss => ss.Set() + .Include(b => b.OrderDetails) + .OrderBy(b => b.Customer.CustomerID != null) + .ThenBy(b => b.Customer != null ? b.Customer.CustomerID : string.Empty) + .Take(2), + entryCount: 6); + } + protected virtual void ClearLog() { } diff --git a/test/EFCore.Specification.Tests/TestModels/TransportationModel/TransportationContext.cs b/test/EFCore.Specification.Tests/TestModels/TransportationModel/TransportationContext.cs index 6751ea8f95a..00a51408b37 100644 --- a/test/EFCore.Specification.Tests/TestModels/TransportationModel/TransportationContext.cs +++ b/test/EFCore.Specification.Tests/TestModels/TransportationModel/TransportationContext.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit; diff --git a/test/EFCore.Specification.Tests/TestUtilities/TestStore.cs b/test/EFCore.Specification.Tests/TestUtilities/TestStore.cs index e57606c4442..d664e9819e3 100644 --- a/test/EFCore.Specification.Tests/TestUtilities/TestStore.cs +++ b/test/EFCore.Specification.Tests/TestUtilities/TestStore.cs @@ -42,7 +42,7 @@ public virtual TestStore Initialize( } else { - Initialize(createContext, seed, clean); + GetTestStoreIndex(serviceProvider).CreateNonShared(GetType().Name + Name, () => Initialize(createContext, seed, clean)); } return this; diff --git a/test/EFCore.Specification.Tests/TestUtilities/TestStoreIndex.cs b/test/EFCore.Specification.Tests/TestUtilities/TestStoreIndex.cs index a50c12ee8b9..afa9ceffcaa 100644 --- a/test/EFCore.Specification.Tests/TestUtilities/TestStoreIndex.cs +++ b/test/EFCore.Specification.Tests/TestUtilities/TestStoreIndex.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Threading; namespace Microsoft.EntityFrameworkCore.TestUtilities { @@ -39,5 +40,31 @@ public virtual void CreateShared(string name, Action initializeDatabase) } } } + + public virtual void CreateNonShared(string name, Action initializeDatabase) + { + var creationLock = _creationLocks.GetOrAdd(name, new object()); + + if (Monitor.TryEnter(creationLock)) + { + try + { + initializeDatabase?.Invoke(); + } + finally + { + Monitor.Exit(creationLock); + if (!_creationLocks.TryRemove(name, out _)) + { + throw new InvalidOperationException($"An attempt was made to initialize a non-shared store {name} from two different threads."); + } + } + } + else + { + _creationLocks.TryRemove(name, out _); + throw new InvalidOperationException($"An attempt was made to initialize a non-shared store {name} from two different threads."); + } + } } } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindIncludeQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindIncludeQuerySqlServerTest.cs index 879c93fd73d..adf71aaf973 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindIncludeQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindIncludeQuerySqlServerTest.cs @@ -1333,6 +1333,36 @@ WHERE [c].[CustomerID] LIKE N'F%' ORDER BY [c].[CustomerID], [t0].[OrderID], [o0].[OrderID], [o0].[ProductID]"); } + public override async Task Repro9735(bool async) + { + await base.Repro9735(async); + + AssertSql( + @"@__p_0='2' + +SELECT [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate], [t].[CustomerID0], [o0].[OrderID], [o0].[ProductID], [o0].[Discount], [o0].[Quantity], [o0].[UnitPrice] +FROM ( + SELECT TOP(@__p_0) [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [c].[CustomerID] AS [CustomerID0], CASE + WHEN [c].[CustomerID] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [c], CASE + WHEN [c].[CustomerID] IS NOT NULL THEN [c].[CustomerID] + ELSE N'' + END AS [c0] + FROM [Orders] AS [o] + LEFT JOIN [Customers] AS [c] ON [o].[CustomerID] = [c].[CustomerID] + ORDER BY CASE + WHEN [c].[CustomerID] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END, CASE + WHEN [c].[CustomerID] IS NOT NULL THEN [c].[CustomerID] + ELSE N'' + END +) AS [t] +LEFT JOIN [Order Details] AS [o0] ON [t].[OrderID] = [o0].[OrderID] +ORDER BY [t].[c], [t].[c0], [t].[OrderID], [t].[CustomerID0], [o0].[OrderID], [o0].[ProductID]"); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs index e28bd2af506..30b56d00860 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs @@ -18,13 +18,12 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.SqlServer.Infrastructure.Internal; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.TestUtilities; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Logging; using NetTopologySuite.Geometries; using Newtonsoft.Json.Linq; using Xunit; @@ -38,7 +37,7 @@ // ReSharper disable UnusedMember.Local namespace Microsoft.EntityFrameworkCore.Query { - public class QueryBugsTest : IClassFixture + public class QueryBugsTest : NonSharedModelTestBase, IClassFixture { // ReSharper disable once UnusedParameter.Local #pragma warning disable IDE0060 // Remove unused parameter @@ -52,33 +51,32 @@ public QueryBugsTest(SqlServerFixture fixture, ITestOutputHelper testOutputHelpe protected SqlServerFixture Fixture { get; } + #region Issue14095 + [ConditionalTheory] [InlineData(false)] [InlineData(true)] public async Task Where_equals_DateTime_Now(bool async) { - using (CreateDateTimeStore()) - { - Fixture.TestSqlLoggerFactory.Clear(); + var contextFactory = await InitializeDateTimeContextAsync(); - using var context = new DateTimeContext(_options); - var query = context.Dates.Where( - d => d.DateTime2_2 == DateTime.Now - || d.DateTime2_7 == DateTime.Now - || d.DateTime == DateTime.Now - || d.SmallDateTime == DateTime.Now); + using var context = contextFactory.CreateContext(); + var query = context.Dates.Where( + d => d.DateTime2_2 == DateTime.Now + || d.DateTime2_7 == DateTime.Now + || d.DateTime == DateTime.Now + || d.SmallDateTime == DateTime.Now); - var results = async - ? await query.ToListAsync() - : query.ToList(); + var results = async + ? await query.ToListAsync() + : query.ToList(); - Assert.Empty(results); + Assert.Empty(results); - AssertSql( - @"SELECT [d].[Id], [d].[DateTime], [d].[DateTime2], [d].[DateTime2_0], [d].[DateTime2_1], [d].[DateTime2_2], [d].[DateTime2_3], [d].[DateTime2_4], [d].[DateTime2_5], [d].[DateTime2_6], [d].[DateTime2_7], [d].[SmallDateTime] + AssertSql( + @"SELECT [d].[Id], [d].[DateTime], [d].[DateTime2], [d].[DateTime2_0], [d].[DateTime2_1], [d].[DateTime2_2], [d].[DateTime2_3], [d].[DateTime2_4], [d].[DateTime2_5], [d].[DateTime2_6], [d].[DateTime2_7], [d].[SmallDateTime] FROM [Dates] AS [d] WHERE ((([d].[DateTime2_2] = GETDATE()) OR ([d].[DateTime2_7] = GETDATE())) OR ([d].[DateTime] = GETDATE())) OR ([d].[SmallDateTime] = GETDATE())"); - } } [ConditionalTheory] @@ -86,28 +84,25 @@ FROM [Dates] AS [d] [InlineData(true)] public async Task Where_not_equals_DateTime_Now(bool async) { - using (CreateDateTimeStore()) - { - Fixture.TestSqlLoggerFactory.Clear(); + var contextFactory = await InitializeDateTimeContextAsync(); - using var context = new DateTimeContext(_options); - var query = context.Dates.Where( - d => d.DateTime2_2 != DateTime.Now - && d.DateTime2_7 != DateTime.Now - && d.DateTime != DateTime.Now - && d.SmallDateTime != DateTime.Now); + using var context = contextFactory.CreateContext(); + var query = context.Dates.Where( + d => d.DateTime2_2 != DateTime.Now + && d.DateTime2_7 != DateTime.Now + && d.DateTime != DateTime.Now + && d.SmallDateTime != DateTime.Now); - var results = async - ? await query.ToListAsync() - : query.ToList(); + var results = async + ? await query.ToListAsync() + : query.ToList(); - Assert.Single(results); + Assert.Single(results); - AssertSql( - @"SELECT [d].[Id], [d].[DateTime], [d].[DateTime2], [d].[DateTime2_0], [d].[DateTime2_1], [d].[DateTime2_2], [d].[DateTime2_3], [d].[DateTime2_4], [d].[DateTime2_5], [d].[DateTime2_6], [d].[DateTime2_7], [d].[SmallDateTime] + AssertSql( + @"SELECT [d].[Id], [d].[DateTime], [d].[DateTime2], [d].[DateTime2_0], [d].[DateTime2_1], [d].[DateTime2_2], [d].[DateTime2_3], [d].[DateTime2_4], [d].[DateTime2_5], [d].[DateTime2_6], [d].[DateTime2_7], [d].[SmallDateTime] FROM [Dates] AS [d] WHERE ((([d].[DateTime2_2] <> GETDATE()) AND ([d].[DateTime2_7] <> GETDATE())) AND ([d].[DateTime] <> GETDATE())) AND ([d].[SmallDateTime] <> GETDATE())"); - } } [ConditionalTheory] @@ -115,35 +110,32 @@ FROM [Dates] AS [d] [InlineData(true)] public async Task Where_equals_new_DateTime(bool async) { - using (CreateDateTimeStore()) - { - Fixture.TestSqlLoggerFactory.Clear(); + var contextFactory = await InitializeDateTimeContextAsync(); - using var context = new DateTimeContext(_options); - var query = context.Dates.Where( - d => d.SmallDateTime == new DateTime(1970, 9, 3, 12, 0, 0) - && d.DateTime == new DateTime(1971, 9, 3, 12, 0, 10, 220) - && d.DateTime2 == new DateTime(1972, 9, 3, 12, 0, 10, 333) - && d.DateTime2_0 == new DateTime(1973, 9, 3, 12, 0, 10) - && d.DateTime2_1 == new DateTime(1974, 9, 3, 12, 0, 10, 500) - && d.DateTime2_2 == new DateTime(1975, 9, 3, 12, 0, 10, 660) - && d.DateTime2_3 == new DateTime(1976, 9, 3, 12, 0, 10, 777) - && d.DateTime2_4 == new DateTime(1977, 9, 3, 12, 0, 10, 888) - && d.DateTime2_5 == new DateTime(1978, 9, 3, 12, 0, 10, 999) - && d.DateTime2_6 == new DateTime(1979, 9, 3, 12, 0, 10, 111) - && d.DateTime2_7 == new DateTime(1980, 9, 3, 12, 0, 10, 222)); + using var context = contextFactory.CreateContext(); + var query = context.Dates.Where( + d => d.SmallDateTime == new DateTime(1970, 9, 3, 12, 0, 0) + && d.DateTime == new DateTime(1971, 9, 3, 12, 0, 10, 220) + && d.DateTime2 == new DateTime(1972, 9, 3, 12, 0, 10, 333) + && d.DateTime2_0 == new DateTime(1973, 9, 3, 12, 0, 10) + && d.DateTime2_1 == new DateTime(1974, 9, 3, 12, 0, 10, 500) + && d.DateTime2_2 == new DateTime(1975, 9, 3, 12, 0, 10, 660) + && d.DateTime2_3 == new DateTime(1976, 9, 3, 12, 0, 10, 777) + && d.DateTime2_4 == new DateTime(1977, 9, 3, 12, 0, 10, 888) + && d.DateTime2_5 == new DateTime(1978, 9, 3, 12, 0, 10, 999) + && d.DateTime2_6 == new DateTime(1979, 9, 3, 12, 0, 10, 111) + && d.DateTime2_7 == new DateTime(1980, 9, 3, 12, 0, 10, 222)); - var results = async - ? await query.ToListAsync() - : query.ToList(); + var results = async + ? await query.ToListAsync() + : query.ToList(); - Assert.Single(results); + Assert.Single(results); - AssertSql( - @"SELECT [d].[Id], [d].[DateTime], [d].[DateTime2], [d].[DateTime2_0], [d].[DateTime2_1], [d].[DateTime2_2], [d].[DateTime2_3], [d].[DateTime2_4], [d].[DateTime2_5], [d].[DateTime2_6], [d].[DateTime2_7], [d].[SmallDateTime] + AssertSql( + @"SELECT [d].[Id], [d].[DateTime], [d].[DateTime2], [d].[DateTime2_0], [d].[DateTime2_1], [d].[DateTime2_2], [d].[DateTime2_3], [d].[DateTime2_4], [d].[DateTime2_5], [d].[DateTime2_6], [d].[DateTime2_7], [d].[SmallDateTime] FROM [Dates] AS [d] WHERE (((((((((([d].[SmallDateTime] = '1970-09-03T12:00:00') AND ([d].[DateTime] = '1971-09-03T12:00:10.220')) AND ([d].[DateTime2] = '1972-09-03T12:00:10.3330000')) AND ([d].[DateTime2_0] = '1973-09-03T12:00:10')) AND ([d].[DateTime2_1] = '1974-09-03T12:00:10.5')) AND ([d].[DateTime2_2] = '1975-09-03T12:00:10.66')) AND ([d].[DateTime2_3] = '1976-09-03T12:00:10.777')) AND ([d].[DateTime2_4] = '1977-09-03T12:00:10.8880')) AND ([d].[DateTime2_5] = '1978-09-03T12:00:10.99900')) AND ([d].[DateTime2_6] = '1979-09-03T12:00:10.111000')) AND ([d].[DateTime2_7] = '1980-09-03T12:00:10.2220000')"); - } } [ConditionalTheory] @@ -166,12 +158,10 @@ public async Task Where_contains_DateTime_literals(bool async) new DateTime(1980, 9, 3, 12, 0, 10, 222) }; - using (CreateDateTimeStore()) - { - Fixture.TestSqlLoggerFactory.Clear(); + var contextFactory = await InitializeDateTimeContextAsync(); - using var context = new DateTimeContext(_options); - var query = context.Dates.Where( + using var context = contextFactory.CreateContext(); + var query = context.Dates.Where( d => dateTimes.Contains(d.SmallDateTime) && dateTimes.Contains(d.DateTime) && dateTimes.Contains(d.DateTime2) @@ -194,112 +184,89 @@ public async Task Where_contains_DateTime_literals(bool async) @"SELECT [d].[Id], [d].[DateTime], [d].[DateTime2], [d].[DateTime2_0], [d].[DateTime2_1], [d].[DateTime2_2], [d].[DateTime2_3], [d].[DateTime2_4], [d].[DateTime2_5], [d].[DateTime2_6], [d].[DateTime2_7], [d].[SmallDateTime] FROM [Dates] AS [d] WHERE ((((((((([d].[SmallDateTime] IN ('1970-09-03T12:00:00', '1971-09-03T12:00:10', '1972-09-03T12:00:10', '1973-09-03T12:00:10', '1974-09-03T12:00:10', '1975-09-03T12:00:10', '1976-09-03T12:00:10', '1977-09-03T12:00:10', '1978-09-03T12:00:10', '1979-09-03T12:00:10', '1980-09-03T12:00:10') AND [d].[DateTime] IN ('1970-09-03T12:00:00.000', '1971-09-03T12:00:10.220', '1972-09-03T12:00:10.333', '1973-09-03T12:00:10.000', '1974-09-03T12:00:10.500', '1975-09-03T12:00:10.660', '1976-09-03T12:00:10.777', '1977-09-03T12:00:10.888', '1978-09-03T12:00:10.999', '1979-09-03T12:00:10.111', '1980-09-03T12:00:10.222')) AND [d].[DateTime2] IN ('1970-09-03T12:00:00.0000000', '1971-09-03T12:00:10.2200000', '1972-09-03T12:00:10.3330000', '1973-09-03T12:00:10.0000000', '1974-09-03T12:00:10.5000000', '1975-09-03T12:00:10.6600000', '1976-09-03T12:00:10.7770000', '1977-09-03T12:00:10.8880000', '1978-09-03T12:00:10.9990000', '1979-09-03T12:00:10.1110000', '1980-09-03T12:00:10.2220000')) AND [d].[DateTime2_0] IN ('1970-09-03T12:00:00', '1971-09-03T12:00:10', '1972-09-03T12:00:10', '1973-09-03T12:00:10', '1974-09-03T12:00:10', '1975-09-03T12:00:10', '1976-09-03T12:00:10', '1977-09-03T12:00:10', '1978-09-03T12:00:10', '1979-09-03T12:00:10', '1980-09-03T12:00:10')) AND [d].[DateTime2_1] IN ('1970-09-03T12:00:00.0', '1971-09-03T12:00:10.2', '1972-09-03T12:00:10.3', '1973-09-03T12:00:10.0', '1974-09-03T12:00:10.5', '1975-09-03T12:00:10.6', '1976-09-03T12:00:10.7', '1977-09-03T12:00:10.8', '1978-09-03T12:00:10.9', '1979-09-03T12:00:10.1', '1980-09-03T12:00:10.2')) AND [d].[DateTime2_2] IN ('1970-09-03T12:00:00.00', '1971-09-03T12:00:10.22', '1972-09-03T12:00:10.33', '1973-09-03T12:00:10.00', '1974-09-03T12:00:10.50', '1975-09-03T12:00:10.66', '1976-09-03T12:00:10.77', '1977-09-03T12:00:10.88', '1978-09-03T12:00:10.99', '1979-09-03T12:00:10.11', '1980-09-03T12:00:10.22')) AND [d].[DateTime2_3] IN ('1970-09-03T12:00:00.000', '1971-09-03T12:00:10.220', '1972-09-03T12:00:10.333', '1973-09-03T12:00:10.000', '1974-09-03T12:00:10.500', '1975-09-03T12:00:10.660', '1976-09-03T12:00:10.777', '1977-09-03T12:00:10.888', '1978-09-03T12:00:10.999', '1979-09-03T12:00:10.111', '1980-09-03T12:00:10.222')) AND [d].[DateTime2_4] IN ('1970-09-03T12:00:00.0000', '1971-09-03T12:00:10.2200', '1972-09-03T12:00:10.3330', '1973-09-03T12:00:10.0000', '1974-09-03T12:00:10.5000', '1975-09-03T12:00:10.6600', '1976-09-03T12:00:10.7770', '1977-09-03T12:00:10.8880', '1978-09-03T12:00:10.9990', '1979-09-03T12:00:10.1110', '1980-09-03T12:00:10.2220')) AND [d].[DateTime2_5] IN ('1970-09-03T12:00:00.00000', '1971-09-03T12:00:10.22000', '1972-09-03T12:00:10.33300', '1973-09-03T12:00:10.00000', '1974-09-03T12:00:10.50000', '1975-09-03T12:00:10.66000', '1976-09-03T12:00:10.77700', '1977-09-03T12:00:10.88800', '1978-09-03T12:00:10.99900', '1979-09-03T12:00:10.11100', '1980-09-03T12:00:10.22200')) AND [d].[DateTime2_6] IN ('1970-09-03T12:00:00.000000', '1971-09-03T12:00:10.220000', '1972-09-03T12:00:10.333000', '1973-09-03T12:00:10.000000', '1974-09-03T12:00:10.500000', '1975-09-03T12:00:10.660000', '1976-09-03T12:00:10.777000', '1977-09-03T12:00:10.888000', '1978-09-03T12:00:10.999000', '1979-09-03T12:00:10.111000', '1980-09-03T12:00:10.222000')) AND [d].[DateTime2_7] IN ('1970-09-03T12:00:00.0000000', '1971-09-03T12:00:10.2200000', '1972-09-03T12:00:10.3330000', '1973-09-03T12:00:10.0000000', '1974-09-03T12:00:10.5000000', '1975-09-03T12:00:10.6600000', '1976-09-03T12:00:10.7770000', '1977-09-03T12:00:10.8880000', '1978-09-03T12:00:10.9990000', '1979-09-03T12:00:10.1110000', '1980-09-03T12:00:10.2220000')"); - } } - private class DatesAndPrunes + protected class DateTimeContext : DbContext { - public int Id { get; set; } + public DateTimeContext(DbContextOptions options) + : base(options) + { + } + + public DbSet Dates { get; set; } - [Column(TypeName = "smalldatetime")] - public DateTime SmallDateTime { get; set; } + public void Seed() + { + Add( + new DatesAndPrunes + { + SmallDateTime = new DateTime(1970, 9, 3, 12, 0, 0), + DateTime = new DateTime(1971, 9, 3, 12, 0, 10, 220), + DateTime2 = new DateTime(1972, 9, 3, 12, 0, 10, 333), + DateTime2_0 = new DateTime(1973, 9, 3, 12, 0, 10), + DateTime2_1 = new DateTime(1974, 9, 3, 12, 0, 10, 500), + DateTime2_2 = new DateTime(1975, 9, 3, 12, 0, 10, 660), + DateTime2_3 = new DateTime(1976, 9, 3, 12, 0, 10, 777), + DateTime2_4 = new DateTime(1977, 9, 3, 12, 0, 10, 888), + DateTime2_5 = new DateTime(1978, 9, 3, 12, 0, 10, 999), + DateTime2_6 = new DateTime(1979, 9, 3, 12, 0, 10, 111), + DateTime2_7 = new DateTime(1980, 9, 3, 12, 0, 10, 222) + }); + SaveChanges(); + } - [Column(TypeName = "datetime")] - public DateTime DateTime { get; set; } + public class DatesAndPrunes + { + public int Id { get; set; } - [Column(TypeName = "datetime2")] - public DateTime DateTime2 { get; set; } + [Column(TypeName = "smalldatetime")] + public DateTime SmallDateTime { get; set; } - [Column(TypeName = "datetime2(0)")] - public DateTime DateTime2_0 { get; set; } + [Column(TypeName = "datetime")] + public DateTime DateTime { get; set; } - [Column(TypeName = "datetime2(1)")] - public DateTime DateTime2_1 { get; set; } + [Column(TypeName = "datetime2")] + public DateTime DateTime2 { get; set; } - [Column(TypeName = "datetime2(2)")] - public DateTime DateTime2_2 { get; set; } + [Column(TypeName = "datetime2(0)")] + public DateTime DateTime2_0 { get; set; } - [Column(TypeName = "datetime2(3)")] - public DateTime DateTime2_3 { get; set; } + [Column(TypeName = "datetime2(1)")] + public DateTime DateTime2_1 { get; set; } - [Column(TypeName = "datetime2(4)")] - public DateTime DateTime2_4 { get; set; } + [Column(TypeName = "datetime2(2)")] + public DateTime DateTime2_2 { get; set; } - [Column(TypeName = "datetime2(5)")] - public DateTime DateTime2_5 { get; set; } + [Column(TypeName = "datetime2(3)")] + public DateTime DateTime2_3 { get; set; } - [Column(TypeName = "datetime2(6)")] - public DateTime DateTime2_6 { get; set; } + [Column(TypeName = "datetime2(4)")] + public DateTime DateTime2_4 { get; set; } - [Column(TypeName = "datetime2(7)")] - public DateTime DateTime2_7 { get; set; } - } + [Column(TypeName = "datetime2(5)")] + public DateTime DateTime2_5 { get; set; } - private class DateTimeContext : DbContext - { - public DateTimeContext(DbContextOptions options) - : base(options) - { - } + [Column(TypeName = "datetime2(6)")] + public DateTime DateTime2_6 { get; set; } - public DbSet Dates { get; set; } + [Column(TypeName = "datetime2(7)")] + public DateTime DateTime2_7 { get; set; } + } } - private SqlServerTestStore CreateDateTimeStore() - => CreateTestStore( - () => new DateTimeContext(_options), - c => - { - c.Add( - new DatesAndPrunes - { - SmallDateTime = new DateTime(1970, 9, 3, 12, 0, 0), - DateTime = new DateTime(1971, 9, 3, 12, 0, 10, 220), - DateTime2 = new DateTime(1972, 9, 3, 12, 0, 10, 333), - DateTime2_0 = new DateTime(1973, 9, 3, 12, 0, 10), - DateTime2_1 = new DateTime(1974, 9, 3, 12, 0, 10, 500), - DateTime2_2 = new DateTime(1975, 9, 3, 12, 0, 10, 660), - DateTime2_3 = new DateTime(1976, 9, 3, 12, 0, 10, 777), - DateTime2_4 = new DateTime(1977, 9, 3, 12, 0, 10, 888), - DateTime2_5 = new DateTime(1978, 9, 3, 12, 0, 10, 999), - DateTime2_6 = new DateTime(1979, 9, 3, 12, 0, 10, 111), - DateTime2_7 = new DateTime(1980, 9, 3, 12, 0, 10, 222) - }); + protected Task> InitializeDateTimeContextAsync() + => InitializeAsync(seed: c => c.Seed()); - c.SaveChanges(); - }); + #endregion - #region Bug6901 + #region Issue6901 [ConditionalFact] - public void Left_outer_join_bug_6091() - { - using var testStore = SqlServerTestStore.CreateInitialized("QueryBugsTest"); - testStore.ExecuteNonQuery( - @" -CREATE TABLE [dbo].[Customers]( - [CustomerID] [int] NOT NULL PRIMARY KEY, - [CustomerName] [varchar](120) NULL, - [PostcodeID] [int] NULL); - -CREATE TABLE [dbo].[Postcodes]( - [PostcodeID] [int] NOT NULL PRIMARY KEY, - [PostcodeValue] [varchar](100) NOT NULL, - [TownName] [varchar](255) NOT NULL); - -INSERT [dbo].[Customers] ([CustomerID], [CustomerName], [PostcodeID]) VALUES (1, N'Sam Tippet', 5); -INSERT [dbo].[Customers] ([CustomerID], [CustomerName], [PostcodeID]) VALUES (2, N'William Greig', 2); -INSERT [dbo].[Customers] ([CustomerID], [CustomerName], [PostcodeID]) VALUES (3, N'Steve Jones', 3); -INSERT [dbo].[Customers] ([CustomerID], [CustomerName], [PostcodeID]) VALUES (4, N'Jim Warren', NULL); -INSERT [dbo].[Customers] ([CustomerID], [CustomerName], [PostcodeID]) VALUES (5, N'Andrew Smith', 5); - -INSERT [dbo].[Postcodes] ([PostcodeID], [PostcodeValue], [TownName]) VALUES (2, N'1000', N'Town 1'); -INSERT [dbo].[Postcodes] ([PostcodeID], [PostcodeValue], [TownName]) VALUES (3, N'2000', N'Town 2'); -INSERT [dbo].[Postcodes] ([PostcodeID], [PostcodeValue], [TownName]) VALUES (4, N'3000', N'Town 3'); -INSERT [dbo].[Postcodes] ([PostcodeID], [PostcodeValue], [TownName]) VALUES (5, N'4000', N'Town 4'); -"); - - using var context = new Bug6091Context(Fixture.CreateOptions(testStore)); + public async Task Left_outer_join_Issue_6091() + { + var contextFactory = await InitializeAsync(); + + using var context = contextFactory.CreateContext(); var customers = from customer in context.Customers join postcode in context.Postcodes @@ -319,16 +286,38 @@ from custPC in custPCTmp.DefaultIfEmpty() Assert.True(results[3].CustomerName != results[4].CustomerName); } - private class Bug6091Context : DbContext + protected class Issue6091Context : DbContext { - public Bug6091Context(DbContextOptions options) + public Issue6091Context(DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { - modelBuilder.Entity().ToTable("Customers"); + modelBuilder.Entity(c => + { + c.Property(c => c.CustomerID).ValueGeneratedNever(); + c.Property(c => c.CustomerName).HasMaxLength(120).IsUnicode(false); + c.HasData( + new Customer { CustomerID = 1, CustomerName = "Sam Tippet", PostcodeID = 5 }, + new Customer { CustomerID = 2, CustomerName = "William Greig", PostcodeID = 2 }, + new Customer { CustomerID = 3, CustomerName = "Steve Jones", PostcodeID = 3 }, + new Customer { CustomerID = 4, CustomerName = "Jim Warren" }, + new Customer { CustomerID = 5, CustomerName = "Andrew Smith", PostcodeID = 5 }); + }); + + modelBuilder.Entity(p => + { + p.Property(c => c.PostcodeID).ValueGeneratedNever(); + p.Property(c => c.PostcodeValue).HasMaxLength(100).IsUnicode(false); + p.Property(c => c.TownName).HasMaxLength(255).IsUnicode(false); + p.HasData( + new Postcode { PostcodeID = 2, PostcodeValue = "1000", TownName = "Town 1" }, + new Postcode { PostcodeID = 3, PostcodeValue = "2000", TownName = "Town 2" }, + new Postcode { PostcodeID = 4, PostcodeValue = "3000", TownName = "Town 3" }, + new Postcode { PostcodeID = 5, PostcodeValue = "4000", TownName = "Town 4" }); + }); } public DbSet Customers { get; set; } @@ -352,15 +341,14 @@ public class Postcode #endregion - #region Bug5481 + #region Issue5481 [ConditionalFact] - public async Task Multiple_optional_navs_should_not_deadlock_bug_5481() + public async Task Multiple_optional_navs_should_not_deadlock_Issue_5481() { - using var testStore = SqlServerTestStore.CreateInitialized("QueryBugsTest"); - using var context = new DeadlockContext(Fixture.CreateOptions(testStore)); - context.Database.EnsureCreatedResiliently(); - context.EnsureSeeded(); + var contextFactory = await InitializeAsync(); + + using var context = contextFactory.CreateContext(); var count = await context.Persons @@ -372,7 +360,7 @@ var count Assert.Equal(0, count); } - private class DeadlockContext : DbContext + protected class DeadlockContext : DbContext { public DeadlockContext(DbContextOptions options) : base(options) @@ -448,24 +436,24 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) #endregion + #region Issue2951 + [ConditionalFact] - public void Query_when_null_key_in_database_should_throw() + public async Task Query_when_null_key_in_database_should_throw() { - using var testStore = SqlServerTestStore.CreateInitialized("QueryBugsTest"); - testStore.ExecuteNonQuery( - @"CREATE TABLE ZeroKey (Id int); - INSERT ZeroKey VALUES (NULL)"); + var contextFactory = await InitializeAsync(onConfiguring: o => o.EnableDetailedErrors()); - var options = Fixture.CreateOptions(testStore); - options = new DbContextOptionsBuilder(options).EnableDetailedErrors().Options; + using var context = contextFactory.CreateContext(); + await context.Database.ExecuteSqlRawAsync(@" +CREATE TABLE ZeroKey (Id int); +INSERT ZeroKey VALUES (NULL)"); - using var context = new NullKeyContext(options); Assert.Equal( RelationalStrings.ErrorMaterializingPropertyNullReference("ZeroKey", "Id", typeof(int)), Assert.Throws(() => context.ZeroKeys.ToList()).Message); } - private class NullKeyContext : DbContext + protected class NullKeyContext : DbContext { public NullKeyContext(DbContextOptions options) : base(options) @@ -474,7 +462,8 @@ public NullKeyContext(DbContextOptions options) protected override void OnModelCreating(ModelBuilder modelBuilder) { - modelBuilder.Entity().ToTable("ZeroKey"); + modelBuilder.Entity().ToTable("ZeroKey", t => t.ExcludeFromMigrations()) + .Property(z => z.Id).ValueGeneratedNever(); } public DbSet ZeroKeys { get; set; } @@ -485,54 +474,42 @@ public class ZeroKey } } - #region Bug603 + #endregion + + #region Issue603 [ConditionalFact] - public async Task First_FirstOrDefault_ix_async_bug_603() + public async Task First_FirstOrDefault_ix_async_Issue_603() { - using (CreateDatabase603()) - { - using (var context = new MyContext603(_options)) - { - context.Products.Add( - new Product { Name = "Product 1" }); - context.SaveChanges(); - } + var contextFactory = await InitializeAsync(); - using var ctx = new MyContext603(_options); - var product = await ctx.Products.OrderBy(p => p.Id).FirstAsync(); + using (var context = contextFactory.CreateContext()) + { + var product = await context.Products.OrderBy(p => p.Id).FirstAsync(); - ctx.Products.Remove(product); + context.Products.Remove(product); - await ctx.SaveChangesAsync(); + await context.SaveChangesAsync(); } - using (CreateDatabase603()) + using (var context = contextFactory.CreateContext()) { - using (var context = new MyContext603(_options)) - { - context.Products.Add( - new Product { Name = "Product 1" }); - context.SaveChanges(); - } + context.Products.Add( + new MyContext603.Product { Name = "Product 1" }); + context.SaveChanges(); + } - using var ctx = new MyContext603(_options); - var product = await ctx.Products.OrderBy(p => p.Id).FirstOrDefaultAsync(); + using (var context = contextFactory.CreateContext()) + { + var product = await context.Products.OrderBy(p => p.Id).FirstOrDefaultAsync(); - ctx.Products.Remove(product); + context.Products.Remove(product); - await ctx.SaveChangesAsync(); + await context.SaveChangesAsync(); } } - private class Product - { - public int Id { get; set; } - - public string Name { get; set; } - } - - private class MyContext603 : DbContext + protected class MyContext603 : DbContext { public MyContext603(DbContextOptions options) : base(options) @@ -543,113 +520,62 @@ public MyContext603(DbContextOptions options) protected override void OnModelCreating(ModelBuilder modelBuilder) { - modelBuilder.Entity().ToTable("Product"); + modelBuilder.Entity().ToTable("Product") + .HasData(new Product { Id = 1, Name = "Product 1" }); } - } - private SqlServerTestStore CreateDatabase603() - { - return CreateTestStore(() => new MyContext603(_options), null); + public class Product + { + public int Id { get; set; } + + public string Name { get; set; } + } } #endregion - #region Bugs925_926 + #region Issues925_926 [ConditionalFact] - public void Include_on_entity_with_composite_key_One_To_Many_bugs_925_926() + public async Task Include_on_entity_with_composite_key_One_To_Many_Issues_925_926() { - using (CreateDatabase925()) - { - using var ctx = new MyContext925(_options); - var query = ctx.Customers.Include(c => c.Orders).OrderBy(c => c.FirstName).ThenBy(c => c.LastName); - var result = query.ToList(); + var contextFactory = await InitializeAsync(); - Assert.Equal(2, result.Count); - Assert.Equal(2, result[0].Orders.Count); - Assert.Equal(3, result[1].Orders.Count); + using var ctx = contextFactory.CreateContext(); + var query = ctx.Customers.Include(c => c.Orders).OrderBy(c => c.FirstName).ThenBy(c => c.LastName); + var result = query.ToList(); - AssertSql( - @"SELECT [c].[FirstName], [c].[LastName], [o].[Id], [o].[CustomerFirstName], [o].[CustomerLastName], [o].[Name] + Assert.Equal(2, result.Count); + Assert.Equal(2, result[0].Orders.Count); + Assert.Equal(3, result[1].Orders.Count); + + AssertSql( + @"SELECT [c].[FirstName], [c].[LastName], [o].[Id], [o].[CustomerFirstName], [o].[CustomerLastName], [o].[Name] FROM [Customer] AS [c] LEFT JOIN [Order] AS [o] ON ([c].[FirstName] = [o].[CustomerFirstName]) AND ([c].[LastName] = [o].[CustomerLastName]) ORDER BY [c].[FirstName], [c].[LastName], [o].[Id]"); - } } [ConditionalFact] - public void Include_on_entity_with_composite_key_Many_To_One_bugs_925_926() + public async Task Include_on_entity_with_composite_key_Many_To_One_Issues_925_926() { - using (CreateDatabase925()) - { - using var ctx = new MyContext925(_options); - var query = ctx.Orders.Include(o => o.Customer); - var result = query.ToList(); + var contextFactory = await InitializeAsync(); - Assert.Equal(5, result.Count); - Assert.NotNull(result[0].Customer); - Assert.NotNull(result[1].Customer); - Assert.NotNull(result[2].Customer); - Assert.NotNull(result[3].Customer); - Assert.NotNull(result[4].Customer); + using var ctx = contextFactory.CreateContext(); + var query = ctx.Orders.Include(o => o.Customer); + var result = query.ToList(); - AssertSql( - @"SELECT [o].[Id], [o].[CustomerFirstName], [o].[CustomerLastName], [o].[Name], [c].[FirstName], [c].[LastName] + Assert.Equal(5, result.Count); + Assert.NotNull(result[0].Customer); + Assert.NotNull(result[1].Customer); + Assert.NotNull(result[2].Customer); + Assert.NotNull(result[3].Customer); + Assert.NotNull(result[4].Customer); + + AssertSql( + @"SELECT [o].[Id], [o].[CustomerFirstName], [o].[CustomerLastName], [o].[Name], [c].[FirstName], [c].[LastName] FROM [Order] AS [o] LEFT JOIN [Customer] AS [c] ON ([o].[CustomerFirstName] = [c].[FirstName]) AND ([o].[CustomerLastName] = [c].[LastName])"); - } - } - - private SqlServerTestStore CreateDatabase925() - { - return CreateTestStore( - () => new MyContext925(_options), - context => - { - var order11 = new Order { Name = "Order11" }; - var order12 = new Order { Name = "Order12" }; - var order21 = new Order { Name = "Order21" }; - var order22 = new Order { Name = "Order22" }; - var order23 = new Order { Name = "Order23" }; - - var customer1 = new Customer - { - FirstName = "Customer", - LastName = "One", - Orders = new List { order11, order12 } - }; - var customer2 = new Customer - { - FirstName = "Customer", - LastName = "Two", - Orders = new List - { - order21, - order22, - order23 - } - }; - - context.Customers.AddRange(customer1, customer2); - context.Orders.AddRange(order11, order12, order21, order22, order23); - context.SaveChanges(); - - ClearLog(); - }); - } - - private class Customer - { - public string FirstName { get; set; } - public string LastName { get; set; } - public List Orders { get; set; } - } - - private class Order - { - public int Id { get; set; } - public string Name { get; set; } - public Customer Customer { get; set; } } private class MyContext925 : DbContext @@ -671,132 +597,99 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) m.HasKey( c => new { c.FirstName, c.LastName }); m.HasMany(c => c.Orders).WithOne(o => o.Customer); + m.HasData(new Customer + { + FirstName = "Customer", + LastName = "One" + }, + new Customer + { + FirstName = "Customer", + LastName = "Two" + }); }); - modelBuilder.Entity().ToTable("Order"); + modelBuilder.Entity().ToTable("Order") + .HasData(new { Id = 1, Name = "Order11", CustomerFirstName = "Customer", CustomerLastName = "One" }, + new { Id = 2, Name = "Order12", CustomerFirstName = "Customer", CustomerLastName = "One" }, + new { Id = 3, Name = "Order21", CustomerFirstName = "Customer", CustomerLastName = "Two" }, + new { Id = 4, Name = "Order22", CustomerFirstName = "Customer", CustomerLastName = "Two" }, + new { Id = 5, Name = "Order23", CustomerFirstName = "Customer", CustomerLastName = "Two" }); } - } - - #endregion - - #region Bug963 - [ConditionalFact] - public void Include_on_optional_navigation_One_To_Many_963() - { - using (CreateDatabase963()) + public class Customer { - using var ctx = new MyContext963(_options); - ctx.Targaryens.Include(t => t.Dragons).ToList(); + public string FirstName { get; set; } + public string LastName { get; set; } + public List Orders { get; set; } } - } - [ConditionalFact] - public void Include_on_optional_navigation_Many_To_One_963() - { - using (CreateDatabase963()) + public class Order { - using var ctx = new MyContext963(_options); - ctx.Dragons.Include(d => d.Mother).ToList(); + public int Id { get; set; } + public string Name { get; set; } + public Customer Customer { get; set; } } } - [ConditionalFact] - public void Include_on_optional_navigation_One_To_One_principal_963() - { - using (CreateDatabase963()) - { - using var ctx = new MyContext963(_options); - ctx.Targaryens.Include(t => t.Details).ToList(); - } - } + #endregion + + #region Issue963 [ConditionalFact] - public void Include_on_optional_navigation_One_To_One_dependent_963() + public async Task Include_on_optional_navigation() { - using (CreateDatabase963()) + var contextFactory = await InitializeAsync(); + + using (var ctx = contextFactory.CreateContext()) { - using var ctx = new MyContext963(_options); - ctx.Details.Include(d => d.Targaryen).ToList(); + var targaryens = ctx.Targaryens.Include(t => t.Dragons).ToList(); + + Assert.All(targaryens, t => Assert.NotNull(t.Dragons)); } - } - [ConditionalFact] - public void Join_on_optional_navigation_One_To_Many_963() - { - using (CreateDatabase963()) + using (var ctx = contextFactory.CreateContext()) { - using var ctx = new MyContext963(_options); - (from t in ctx.Targaryens - join d in ctx.Dragons on t.Id equals d.MotherId - select d).ToList(); - } - } + var dragons = ctx.Dragons.Include(d => d.Mother).ToList(); - private SqlServerTestStore CreateDatabase963() - { - return CreateTestStore( - () => new MyContext963(_options), - context => - { - var drogon = new Dragon { Name = "Drogon" }; - var rhaegal = new Dragon { Name = "Rhaegal" }; - var viserion = new Dragon { Name = "Viserion" }; - var balerion = new Dragon { Name = "Balerion" }; + dragons = dragons.OrderBy(d => d.Id).ToList(); - var aerys = new Targaryen { Name = "Aerys II" }; - var details = new Details - { - FullName = @"Daenerys Stormborn of the House Targaryen, the First of Her Name, the Unburnt, Queen of Meereen, -Queen of the Andals and the Rhoynar and the First Men, Khaleesi of the Great Grass Sea, Breaker of Chains, and Mother of Dragons" - }; + Assert.Collection(dragons, + t => Assert.NotNull(t.Mother), + t => Assert.NotNull(t.Mother), + t => Assert.NotNull(t.Mother), + t => Assert.Null(t.Mother)); + } - var daenerys = new Targaryen - { - Name = "Daenerys", - Details = details, - Dragons = new List - { - drogon, - rhaegal, - viserion - } - }; - context.Targaryens.AddRange(daenerys, aerys); - context.Dragons.AddRange(drogon, rhaegal, viserion, balerion); - context.Details.Add(details); + using (var ctx = contextFactory.CreateContext()) + { + var targaryens = ctx.Targaryens.Include(t => t.Details).ToList(); - context.SaveChanges(); - }); - } + targaryens = targaryens.OrderBy(d => d.Id).ToList(); - private class Targaryen - { - public int Id { get; set; } - public string Name { get; set; } - public Details Details { get; set; } + Assert.Collection(targaryens, + t => Assert.Null(t.Details), + t => Assert.NotNull(t.Details)); + } - public List Dragons { get; set; } - } + using (var ctx = contextFactory.CreateContext()) + { + var details = ctx.Details.Include(d => d.Targaryen).ToList(); - private class Dragon - { - public int Id { get; set; } - public string Name { get; set; } - public int? MotherId { get; set; } - public Targaryen Mother { get; set; } - } + Assert.All(details, t => Assert.NotNull(t.Targaryen)); + } - private class Details - { - public int Id { get; set; } - public int? TargaryenId { get; set; } - public Targaryen Targaryen { get; set; } - public string FullName { get; set; } + using (var ctx = contextFactory.CreateContext()) + { + var dragons = (from t in ctx.Targaryens + join d in ctx.Dragons on t.Id equals d.MotherId + select d).ToList(); + + Assert.Equal(3, dragons.Count()); + } } - // TODO: replace with GearsOfWar context when it's refactored properly - private class MyContext963 : DbContext + protected class MyContext963 : DbContext { public MyContext963(DbContextOptions options) : base(options) @@ -805,8 +698,7 @@ public MyContext963(DbContextOptions options) public DbSet Targaryens { get; set; } - // ReSharper disable once MemberHidesStaticFromOuterClass - public DbSet
Details { get; set; } + public DbSet Details { get; set; } public DbSet Dragons { get; set; } @@ -818,34 +710,71 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) m.ToTable("Targaryen"); m.HasKey(t => t.Id); m.HasMany(t => t.Dragons).WithOne(d => d.Mother).HasForeignKey(d => d.MotherId); - m.HasOne(t => t.Details).WithOne(d => d.Targaryen).HasForeignKey
(d => d.TargaryenId); + m.HasOne(t => t.Details).WithOne(d => d.Targaryen).HasForeignKey(d => d.TargaryenId); + m.HasData(new Targaryen { Id = 1, Name = "Aerys II" }, + new Targaryen { Id = 2, Name = "Daenerys" }); }); - modelBuilder.Entity().ToTable("Dragon"); + modelBuilder.Entity().HasData(new TargaryenDetails + { + Id = 2, + TargaryenId = 2, + FullName = @"Daenerys Stormborn of the House Targaryen, the First of Her Name, the Unburnt, Queen of Meereen, +Queen of the Andals and the Rhoynar and the First Men, Khaleesi of the Great Grass Sea, Breaker of Chains, and Mother of Dragons" + }); + + modelBuilder.Entity().ToTable("Dragon") + .HasData(new Dragon { Id = 1, Name = "Drogon", MotherId =2 }, + new Dragon { Id = 2, Name = "Rhaegal", MotherId = 2 }, + new Dragon { Id = 3, Name = "Viserion", MotherId = 2 }, + new Dragon { Id = 4, Name = "Balerion" }); + } + + public class Targaryen + { + public int Id { get; set; } + public string Name { get; set; } + public TargaryenDetails Details { get; set; } + + public List Dragons { get; set; } + } + + public class Dragon + { + public int Id { get; set; } + public string Name { get; set; } + public int? MotherId { get; set; } + public Targaryen Mother { get; set; } + } + + public class TargaryenDetails + { + public int Id { get; set; } + public int? TargaryenId { get; set; } + public Targaryen Targaryen { get; set; } + public string FullName { get; set; } } } #endregion - #region Bug1742 + #region Issue1742 [ConditionalFact] public void Compiler_generated_local_closure_produces_valid_parameter_name_1742() { - Execute1742( - new CustomerDetails_1742 { FirstName = "Foo", LastName = "Bar" }); + Execute1742(new CustomerDetails_1742 { FirstName = "Foo", LastName = "Bar" }); } private void Execute1742(CustomerDetails_1742 details) { - using (CreateDatabase925()) - { - using var ctx = new MyContext925(_options); - var firstName = details.FirstName; - ctx.Customers.Where(c => c.FirstName == firstName && c.LastName == details.LastName).ToList(); + var contextFactory = Initialize(); - // No AssertSQL since compiler generated variable names are different between local and CI - } + using var ctx = contextFactory.CreateContext(); + var firstName = details.FirstName; + ctx.Customers.Where(c => c.FirstName == firstName && c.LastName == details.LastName).ToList(); + + // No AssertSQL since compiler generated variable names are different between local and CI } private class CustomerDetails_1742 @@ -856,49 +785,49 @@ private class CustomerDetails_1742 #endregion - #region Bug3758 + #region Issue3758 [ConditionalFact] - public void Customer_collections_materialize_properly_3758() + public async Task Customer_collections_materialize_properly_3758() { - using (CreateDatabase3758()) - { - using var ctx = new MyContext3758(_options); - var query1 = ctx.Customers.Select(c => c.Orders1); - var result1 = query1.ToList(); + var contextFactory = await InitializeAsync(seed: c => c.Seed()); - Assert.Equal(2, result1.Count); - Assert.IsType>(result1[0]); - Assert.Equal(2, result1[0].Count); - Assert.Equal(2, result1[1].Count); + using var ctx = contextFactory.CreateContext(); - var query2 = ctx.Customers.Select(c => c.Orders2); - var result2 = query2.ToList(); + var query1 = ctx.Customers.Select(c => c.Orders1); + var result1 = query1.ToList(); - Assert.Equal(2, result2.Count); - Assert.IsType>(result2[0]); - Assert.Equal(2, result2[0].Count); - Assert.Equal(2, result2[1].Count); + Assert.Equal(2, result1.Count); + Assert.IsType>(result1[0]); + Assert.Equal(2, result1[0].Count); + Assert.Equal(2, result1[1].Count); - var query3 = ctx.Customers.Select(c => c.Orders3); - var result3 = query3.ToList(); + var query2 = ctx.Customers.Select(c => c.Orders2); + var result2 = query2.ToList(); - Assert.Equal(2, result3.Count); - Assert.IsType(result3[0]); - Assert.Equal(2, result3[0].Count); - Assert.Equal(2, result3[1].Count); + Assert.Equal(2, result2.Count); + Assert.IsType>(result2[0]); + Assert.Equal(2, result2[0].Count); + Assert.Equal(2, result2[1].Count); - var query4 = ctx.Customers.Select(c => c.Orders4); + var query3 = ctx.Customers.Select(c => c.Orders3); + var result3 = query3.ToList(); - Assert.Equal( - CoreStrings.NavigationCannotCreateType( - "Orders4", typeof(Customer3758).Name, - typeof(MyInvalidCollection3758).ShortDisplayName()), - Assert.Throws(() => query4.ToList()).Message); - } + Assert.Equal(2, result3.Count); + Assert.IsType(result3[0]); + Assert.Equal(2, result3[0].Count); + Assert.Equal(2, result3[1].Count); + + var query4 = ctx.Customers.Select(c => c.Orders4); + + Assert.Equal( + CoreStrings.NavigationCannotCreateType( + "Orders4", typeof(MyContext3758.Customer3758).Name, + typeof(MyContext3758.MyInvalidCollection3758).ShortDisplayName()), + Assert.Throws(() => query4.ToList()).Message); } - private class MyContext3758 : DbContext + protected class MyContext3758 : DbContext { public MyContext3758(DbContextOptions options) : base(options) @@ -923,164 +852,158 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity().ToTable("Order3758"); } - } - private class Customer3758 - { - public int Id { get; set; } - public string Name { get; set; } + public void Seed() + { + var o111 = new Order3758 { Name = "O111" }; + var o112 = new Order3758 { Name = "O112" }; + var o121 = new Order3758 { Name = "O121" }; + var o122 = new Order3758 { Name = "O122" }; + var o131 = new Order3758 { Name = "O131" }; + var o132 = new Order3758 { Name = "O132" }; + var o141 = new Order3758 { Name = "O141" }; - public ICollection Orders1 { get; set; } - public MyGenericCollection3758 Orders2 { get; set; } - public MyNonGenericCollection3758 Orders3 { get; set; } - public MyInvalidCollection3758 Orders4 { get; set; } - } + var o211 = new Order3758 { Name = "O211" }; + var o212 = new Order3758 { Name = "O212" }; + var o221 = new Order3758 { Name = "O221" }; + var o222 = new Order3758 { Name = "O222" }; + var o231 = new Order3758 { Name = "O231" }; + var o232 = new Order3758 { Name = "O232" }; + var o241 = new Order3758 { Name = "O241" }; - private class Order3758 - { - public int Id { get; set; } - public string Name { get; set; } - } + var c1 = new Customer3758 + { + Name = "C1", + Orders1 = new List { o111, o112 }, + Orders2 = new MyGenericCollection3758(), + Orders3 = new MyNonGenericCollection3758(), + Orders4 = new MyInvalidCollection3758(42) + }; - private class MyGenericCollection3758 : List - { - } + c1.Orders2.AddRange(new[] { o121, o122 }); + c1.Orders3.AddRange(new[] { o131, o132 }); + c1.Orders4.Add(o141); - private class MyNonGenericCollection3758 : List - { - } + var c2 = new Customer3758 + { + Name = "C2", + Orders1 = new List { o211, o212 }, + Orders2 = new MyGenericCollection3758(), + Orders3 = new MyNonGenericCollection3758(), + Orders4 = new MyInvalidCollection3758(42) + }; - private class MyInvalidCollection3758 : List - { - public MyInvalidCollection3758(int argument) - { - var _ = argument; + c2.Orders2.AddRange(new[] { o221, o222 }); + c2.Orders3.AddRange(new[] { o231, o232 }); + c2.Orders4.Add(o241); + + Customers.AddRange(c1, c2); + Orders.AddRange( + o111, o112, o121, o122, + o131, o132, o141, o211, + o212, o221, o222, o231, + o232, o241); + + SaveChanges(); } - } - private SqlServerTestStore CreateDatabase3758() - { - return CreateTestStore( - () => new MyContext3758(_options), - context => - { - var o111 = new Order3758 { Name = "O111" }; - var o112 = new Order3758 { Name = "O112" }; - var o121 = new Order3758 { Name = "O121" }; - var o122 = new Order3758 { Name = "O122" }; - var o131 = new Order3758 { Name = "O131" }; - var o132 = new Order3758 { Name = "O132" }; - var o141 = new Order3758 { Name = "O141" }; - - var o211 = new Order3758 { Name = "O211" }; - var o212 = new Order3758 { Name = "O212" }; - var o221 = new Order3758 { Name = "O221" }; - var o222 = new Order3758 { Name = "O222" }; - var o231 = new Order3758 { Name = "O231" }; - var o232 = new Order3758 { Name = "O232" }; - var o241 = new Order3758 { Name = "O241" }; - - var c1 = new Customer3758 - { - Name = "C1", - Orders1 = new List { o111, o112 }, - Orders2 = new MyGenericCollection3758(), - Orders3 = new MyNonGenericCollection3758(), - Orders4 = new MyInvalidCollection3758(42) - }; + public class Customer3758 + { + public int Id { get; set; } + public string Name { get; set; } - c1.Orders2.AddRange(new[] { o121, o122 }); - c1.Orders3.AddRange(new[] { o131, o132 }); - c1.Orders4.Add(o141); + public ICollection Orders1 { get; set; } + public MyGenericCollection3758 Orders2 { get; set; } + public MyNonGenericCollection3758 Orders3 { get; set; } + public MyInvalidCollection3758 Orders4 { get; set; } + } - var c2 = new Customer3758 - { - Name = "C2", - Orders1 = new List { o211, o212 }, - Orders2 = new MyGenericCollection3758(), - Orders3 = new MyNonGenericCollection3758(), - Orders4 = new MyInvalidCollection3758(42) - }; + public class Order3758 + { + public int Id { get; set; } + public string Name { get; set; } + } - c2.Orders2.AddRange(new[] { o221, o222 }); - c2.Orders3.AddRange(new[] { o231, o232 }); - c2.Orders4.Add(o241); + public class MyGenericCollection3758 : List + { + } - context.Customers.AddRange(c1, c2); - context.Orders.AddRange( - o111, o112, o121, o122, - o131, o132, o141, o211, - o212, o221, o222, o231, - o232, o241); + public class MyNonGenericCollection3758 : List + { + } - context.SaveChanges(); - }); + public class MyInvalidCollection3758 : List + { + public MyInvalidCollection3758(int argument) + { + var _ = argument; + } + } } #endregion - #region Bug3409 + #region Issue3409 [ConditionalFact] - public void ThenInclude_with_interface_navigations_3409() + public async Task ThenInclude_with_interface_navigations_3409() { - using (CreateDatabase3409()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using (var context = new MyContext3409(_options)) - { - var results = context.Parents - .Include(p => p.ChildCollection) - .ThenInclude(c => c.SelfReferenceCollection) - .ToList(); - - Assert.Single(results); - Assert.Equal(1, results[0].ChildCollection.Count); - Assert.Equal(2, results[0].ChildCollection.Single().SelfReferenceCollection.Count); - } + var results = context.Parents + .Include(p => p.ChildCollection) + .ThenInclude(c => c.SelfReferenceCollection) + .ToList(); - using (var context = new MyContext3409(_options)) - { - var results = context.Children - .Select( - c => new { c.SelfReferenceBackNavigation, c.SelfReferenceBackNavigation.ParentBackNavigation }) - .ToList(); - - Assert.Equal(3, results.Count); - Assert.Equal(2, results.Count(c => c.SelfReferenceBackNavigation != null)); - Assert.Equal(2, results.Count(c => c.ParentBackNavigation != null)); - } + Assert.Single(results); + Assert.Equal(1, results[0].ChildCollection.Count); + Assert.Equal(2, results[0].ChildCollection.Single().SelfReferenceCollection.Count); + } - using (var context = new MyContext3409(_options)) - { - var results = context.Children - .Select( - c => new - { - SelfReferenceBackNavigation - = EF.Property(c, "SelfReferenceBackNavigation"), - ParentBackNavigationB - = EF.Property( - EF.Property(c, "SelfReferenceBackNavigation"), - "ParentBackNavigation") - }) - .ToList(); - - Assert.Equal(3, results.Count); - Assert.Equal(2, results.Count(c => c.SelfReferenceBackNavigation != null)); - Assert.Equal(2, results.Count(c => c.ParentBackNavigationB != null)); - } + using (var context = contextFactory.CreateContext()) + { + var results = context.Children + .Select( + c => new { c.SelfReferenceBackNavigation, c.SelfReferenceBackNavigation.ParentBackNavigation }) + .ToList(); - using (var context = new MyContext3409(_options)) - { - var results = context.Children - .Include(c => c.SelfReferenceBackNavigation) - .ThenInclude(c => c.ParentBackNavigation) - .ToList(); - - Assert.Equal(3, results.Count); - Assert.Equal(2, results.Count(c => c.SelfReferenceBackNavigation != null)); - Assert.Equal(1, results.Count(c => c.ParentBackNavigation != null)); - } + Assert.Equal(3, results.Count); + Assert.Equal(2, results.Count(c => c.SelfReferenceBackNavigation != null)); + Assert.Equal(2, results.Count(c => c.ParentBackNavigation != null)); + } + + using (var context = contextFactory.CreateContext()) + { + var results = context.Children + .Select( + c => new + { + SelfReferenceBackNavigation + = EF.Property(c, "SelfReferenceBackNavigation"), + ParentBackNavigationB + = EF.Property( + EF.Property(c, "SelfReferenceBackNavigation"), + "ParentBackNavigation") + }) + .ToList(); + + Assert.Equal(3, results.Count); + Assert.Equal(2, results.Count(c => c.SelfReferenceBackNavigation != null)); + Assert.Equal(2, results.Count(c => c.ParentBackNavigationB != null)); + } + + using (var context = contextFactory.CreateContext()) + { + var results = context.Children + .Include(c => c.SelfReferenceBackNavigation) + .ThenInclude(c => c.ParentBackNavigation) + .ToList(); + + Assert.Equal(3, results.Count); + Assert.Equal(2, results.Count(c => c.SelfReferenceBackNavigation != null)); + Assert.Equal(1, results.Count(c => c.ParentBackNavigation != null)); } } @@ -1104,78 +1027,74 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasMany(c => (ICollection)c.SelfReferenceCollection) .WithOne(c => (Child3409)c.SelfReferenceBackNavigation); } - } - private interface IParent3409 - { - int Id { get; set; } + public void Seed() + { + var parent1 = new Parent3409(); - ICollection ChildCollection { get; set; } - } + var child1 = new Child3409(); + var child2 = new Child3409(); + var child3 = new Child3409(); - private interface IChild3409 - { - int Id { get; set; } + parent1.ChildCollection = new List { child1 }; + child1.SelfReferenceCollection = new List { child2, child3 }; - int? ParentBackNavigationId { get; set; } - IParent3409 ParentBackNavigation { get; set; } + Parents.AddRange(parent1); + Children.AddRange(child1, child2, child3); - ICollection SelfReferenceCollection { get; set; } - int? SelfReferenceBackNavigationId { get; set; } - IChild3409 SelfReferenceBackNavigation { get; set; } - } + SaveChanges(); + } - private class Parent3409 : IParent3409 - { - public int Id { get; set; } + public interface IParent3409 + { + int Id { get; set; } - public ICollection ChildCollection { get; set; } - } + ICollection ChildCollection { get; set; } + } - private class Child3409 : IChild3409 - { - public int Id { get; set; } + public interface IChild3409 + { + int Id { get; set; } - public int? ParentBackNavigationId { get; set; } - public IParent3409 ParentBackNavigation { get; set; } + int? ParentBackNavigationId { get; set; } + IParent3409 ParentBackNavigation { get; set; } - public ICollection SelfReferenceCollection { get; set; } - public int? SelfReferenceBackNavigationId { get; set; } - public IChild3409 SelfReferenceBackNavigation { get; set; } - } + ICollection SelfReferenceCollection { get; set; } + int? SelfReferenceBackNavigationId { get; set; } + IChild3409 SelfReferenceBackNavigation { get; set; } + } - private SqlServerTestStore CreateDatabase3409() - { - return CreateTestStore( - () => new MyContext3409(_options), - context => - { - var parent1 = new Parent3409(); + public class Parent3409 : IParent3409 + { + public int Id { get; set; } - var child1 = new Child3409(); - var child2 = new Child3409(); - var child3 = new Child3409(); + public ICollection ChildCollection { get; set; } + } - parent1.ChildCollection = new List { child1 }; - child1.SelfReferenceCollection = new List { child2, child3 }; + public class Child3409 : IChild3409 + { + public int Id { get; set; } - context.Parents.AddRange(parent1); - context.Children.AddRange(child1, child2, child3); + public int? ParentBackNavigationId { get; set; } + public IParent3409 ParentBackNavigation { get; set; } - context.SaveChanges(); - }); + public ICollection SelfReferenceCollection { get; set; } + public int? SelfReferenceBackNavigationId { get; set; } + public IChild3409 SelfReferenceBackNavigation { get; set; } + } } #endregion - #region Bug3101 + #region Issue3101 [ConditionalFact] - public virtual void Repro3101_simple_coalesce1() + public virtual async Task Repro3101_simple_coalesce() { - using (CreateDatabase3101()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var ctx = contextFactory.CreateContext()) { - using var ctx = new MyContext3101(_options); var query = from eVersion in ctx.Entities.Include(e => e.Children) join eRoot in ctx.Entities on eVersion.RootEntityId equals eRoot.Id @@ -1184,16 +1103,12 @@ from eRootJoined in RootEntities.DefaultIfEmpty() select eRootJoined ?? eVersion; var result = query.ToList(); + Assert.True(result.All(e => e.Children.Count > 0)); } - } - [ConditionalFact] - public virtual void Repro3101_simple_coalesce2() - { - using (CreateDatabase3101()) + using (var ctx = contextFactory.CreateContext()) { - using var ctx = new MyContext3101(_options); var query = from eVersion in ctx.Entities join eRoot in ctx.Entities.Include(e => e.Children) on eVersion.RootEntityId equals eRoot.Id @@ -1202,34 +1117,32 @@ from eRootJoined in RootEntities.DefaultIfEmpty() select eRootJoined ?? eVersion; var result = query.ToList(); + Assert.Equal(2, result.Count(e => e.Children.Count > 0)); } - } - [ConditionalFact] - public virtual void Repro3101_simple_coalesce3() - { - using (CreateDatabase3101()) + using (var ctx = contextFactory.CreateContext()) { - using var ctx = new MyContext3101(_options); var query = from eVersion in ctx.Entities.Include(e => e.Children) - join eRoot in ctx.Entities.Include(e => e.Children) - on eVersion.RootEntityId equals eRoot.Id - into RootEntities - from eRootJoined in RootEntities.DefaultIfEmpty() - select eRootJoined ?? eVersion; + join eRoot in ctx.Entities.Include(e => e.Children) + on eVersion.RootEntityId equals eRoot.Id + into RootEntities + from eRootJoined in RootEntities.DefaultIfEmpty() + select eRootJoined ?? eVersion; var result = query.ToList(); + Assert.True(result.All(e => e.Children.Count > 0)); } } [ConditionalFact] - public virtual void Repro3101_complex_coalesce1() + public virtual async Task Repro3101_complex_coalesce() { - using (CreateDatabase3101()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var ctx = contextFactory.CreateContext()) { - using var ctx = new MyContext3101(_options); var query = from eVersion in ctx.Entities.Include(e => e.Children) join eRoot in ctx.Entities on eVersion.RootEntityId equals eRoot.Id @@ -1238,34 +1151,32 @@ from eRootJoined in RootEntities.DefaultIfEmpty() select new { One = 1, Coalesce = eRootJoined ?? eVersion }; var result = query.ToList(); + Assert.True(result.All(e => e.Coalesce.Children.Count > 0)); } - } - [ConditionalFact] - public virtual void Repro3101_complex_coalesce2() - { - using (CreateDatabase3101()) + using (var ctx = contextFactory.CreateContext()) { - using var ctx = new MyContext3101(_options); var query = from eVersion in ctx.Entities - join eRoot in ctx.Entities.Include(e => e.Children) - on eVersion.RootEntityId equals eRoot.Id - into RootEntities - from eRootJoined in RootEntities.DefaultIfEmpty() - select new { Root = eRootJoined, Coalesce = eRootJoined ?? eVersion }; + join eRoot in ctx.Entities.Include(e => e.Children) + on eVersion.RootEntityId equals eRoot.Id + into RootEntities + from eRootJoined in RootEntities.DefaultIfEmpty() + select new { Root = eRootJoined, Coalesce = eRootJoined ?? eVersion }; var result = query.ToList(); + Assert.Equal(2, result.Count(e => e.Coalesce.Children.Count > 0)); } } [ConditionalFact] - public virtual void Repro3101_nested_coalesce1() + public virtual async Task Repro3101_nested_coalesce() { - using (CreateDatabase3101()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var ctx = contextFactory.CreateContext()) { - using var ctx = new MyContext3101(_options); var query = from eVersion in ctx.Entities join eRoot in ctx.Entities.Include(e => e.Children) on eVersion.RootEntityId equals eRoot.Id @@ -1277,14 +1188,9 @@ from eRootJoined in RootEntities.DefaultIfEmpty() var result = query.ToList(); Assert.Equal(2, result.Count(e => e.Coalesce.Children.Count > 0)); } - } - [ConditionalFact] - public virtual void Repro3101_nested_coalesce2() - { - using (CreateDatabase3101()) + using (var ctx = contextFactory.CreateContext()) { - using var ctx = new MyContext3101(_options); var query = from eVersion in ctx.Entities.Include(e => e.Children) join eRoot in ctx.Entities on eVersion.RootEntityId equals eRoot.Id @@ -1304,11 +1210,12 @@ from eRootJoined in RootEntities.DefaultIfEmpty() } [ConditionalFact] - public virtual void Repro3101_conditional() + public virtual async Task Repro3101_conditional() { - using (CreateDatabase3101()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var ctx = contextFactory.CreateContext()) { - using var ctx = new MyContext3101(_options); var query = from eVersion in ctx.Entities.Include(e => e.Children) join eRoot in ctx.Entities on eVersion.RootEntityId equals eRoot.Id @@ -1325,11 +1232,12 @@ from eRootJoined in RootEntities.DefaultIfEmpty() } [ConditionalFact] - public virtual void Repro3101_coalesce_tracking() + public virtual async Task Repro3101_coalesce_tracking() { - using (CreateDatabase3101()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var ctx = contextFactory.CreateContext()) { - using var ctx = new MyContext3101(_options); var query = from eVersion in ctx.Entities join eRoot in ctx.Entities on eVersion.RootEntityId equals eRoot.Id @@ -1348,33 +1256,6 @@ from eRootJoined in RootEntities.DefaultIfEmpty() } } - private SqlServerTestStore CreateDatabase3101() - { - return CreateTestStore( - () => new MyContext3101(_options), - context => - { - var c11 = new Child3101 { Name = "c11" }; - var c12 = new Child3101 { Name = "c12" }; - var c13 = new Child3101 { Name = "c13" }; - var c21 = new Child3101 { Name = "c21" }; - var c22 = new Child3101 { Name = "c22" }; - var c31 = new Child3101 { Name = "c31" }; - var c32 = new Child3101 { Name = "c32" }; - - context.Children.AddRange(c11, c12, c13, c21, c22, c31, c32); - - var e1 = new Entity3101 { Id = 1, Children = new[] { c11, c12, c13 } }; - var e2 = new Entity3101 { Id = 2, Children = new[] { c21, c22 } }; - var e3 = new Entity3101 { Id = 3, Children = new[] { c31, c32 } }; - - e2.RootEntity = e1; - - context.Entities.AddRange(e1, e2, e3); - context.SaveChanges(); - }); - } - private class MyContext3101 : DbContext { public MyContext3101(DbContextOptions options) @@ -1389,68 +1270,84 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity().Property(e => e.Id).ValueGeneratedNever(); } - } - private class Entity3101 - { - public Entity3101() + public void Seed() { - Children = new Collection(); + var c11 = new Child3101 { Name = "c11" }; + var c12 = new Child3101 { Name = "c12" }; + var c13 = new Child3101 { Name = "c13" }; + var c21 = new Child3101 { Name = "c21" }; + var c22 = new Child3101 { Name = "c22" }; + var c31 = new Child3101 { Name = "c31" }; + var c32 = new Child3101 { Name = "c32" }; + + Children.AddRange(c11, c12, c13, c21, c22, c31, c32); + + var e1 = new Entity3101 { Id = 1, Children = new[] { c11, c12, c13 } }; + var e2 = new Entity3101 { Id = 2, Children = new[] { c21, c22 } }; + var e3 = new Entity3101 { Id = 3, Children = new[] { c31, c32 } }; + + e2.RootEntity = e1; + + Entities.AddRange(e1, e2, e3); + SaveChanges(); } - public int Id { get; set; } + public class Entity3101 + { + public Entity3101() + { + Children = new Collection(); + } + + public int Id { get; set; } - public int? RootEntityId { get; set; } + public int? RootEntityId { get; set; } - public Entity3101 RootEntity { get; set; } + public Entity3101 RootEntity { get; set; } - public ICollection Children { get; set; } - } + public ICollection Children { get; set; } + } - private class Child3101 - { - public int Id { get; set; } - public string Name { get; set; } + public class Child3101 + { + public int Id { get; set; } + public string Name { get; set; } + } } #endregion - #region Bug6986 + #region Issue6986 [ConditionalFact] - public virtual void Repro6986_can_query_base_type_when_derived_types_contain_shadow_properties() + public virtual async Task Repro6986() { - using (CreateDatabase6986()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new ReproContext6986(_options); + // can_query_base_type_when_derived_types_contain_shadow_properties var query = context.Contacts.ToList(); Assert.Equal(4, query.Count); - Assert.Equal(2, query.OfType().Count()); - Assert.Single(query.OfType()); + Assert.Equal(2, query.OfType().Count()); + Assert.Single(query.OfType()); } - } - [ConditionalFact] - public virtual void Repro6986_can_include_dependent_to_principal_navigation_of_derived_type_with_shadow_fk() - { - using (CreateDatabase6986()) + using (var context = contextFactory.CreateContext()) { - using var context = new ReproContext6986(_options); - var query = context.Contacts.OfType().Include(e => e.ServiceOperator6986).ToList(); + // can_include_dependent_to_principal_navigation_of_derived_type_with_shadow_fk + var query = context.Contacts.OfType().Include(e => e.ServiceOperator6986).ToList(); Assert.Single(query); Assert.NotNull(query[0].ServiceOperator6986); } - } - [ConditionalFact] - public virtual void Repro6986_can_project_shadow_property_using_ef_property() - { - using (CreateDatabase6986()) + using (var context = contextFactory.CreateContext()) { - using var context = new ReproContext6986(_options); - var query = context.Contacts.OfType().Select( + // can_project_shadow_property_using_ef_property + var query = context.Contacts.OfType().Select( c => new { c, Prop = EF.Property(c, "ServiceOperator6986Id") }).ToList(); Assert.Single(query); @@ -1458,40 +1355,6 @@ public virtual void Repro6986_can_project_shadow_property_using_ef_property() } } - private SqlServerTestStore CreateDatabase6986() - { - return CreateTestStore( - () => new ReproContext6986(_options), - context => - { - context.ServiceOperators.Add(new ServiceOperator6986()); - context.Employers.AddRange( - new Employer6986 { Name = "UWE" }, - new Employer6986 { Name = "Hewlett Packard" }); - - context.SaveChanges(); - - context.Contacts.AddRange( - new ServiceOperatorContact6986 - { - UserName = "service.operator@esoterix.co.uk", - ServiceOperator6986 = context.ServiceOperators.OrderBy(o => o.Id).First() - }, - new EmployerContact6986 - { - UserName = "uwe@esoterix.co.uk", - Employer6986 = context.Employers.OrderBy(e => e.Id).First(e => e.Name == "UWE") - }, - new EmployerContact6986 - { - UserName = "hp@esoterix.co.uk", - Employer6986 = context.Employers.OrderBy(e => e.Id).First(e => e.Name == "Hewlett Packard") - }, - new Contact6986 { UserName = "noroles@esoterix.co.uk" }); - context.SaveChanges(); - }); - } - private class ReproContext6986 : DbContext { public ReproContext6986(DbContextOptions options) @@ -1504,173 +1367,148 @@ public ReproContext6986(DbContextOptions options) public DbSet Employers { get; set; } public DbSet ServiceOperatorContacts { get; set; } public DbSet ServiceOperators { get; set; } - } - - private class EmployerContact6986 : Contact6986 - { - [Required] - public Employer6986 Employer6986 { get; set; } - } - - private class ServiceOperatorContact6986 : Contact6986 - { - [Required] - public ServiceOperator6986 ServiceOperator6986 { get; set; } - } - - private class Contact6986 - { - public int Id { get; set; } - public string UserName { get; set; } - public bool IsPrimary { get; set; } - } - - private class Employer6986 - { - public int Id { get; set; } - public string Name { get; set; } - public List Contacts { get; set; } - } - - private class ServiceOperator6986 - { - public int Id { get; set; } - public List Contacts { get; set; } - } - #endregion + public void Seed() + { + ServiceOperators.Add(new ServiceOperator6986()); + Employers.AddRange( + new Employer6986 { Name = "UWE" }, + new Employer6986 { Name = "Hewlett Packard" }); - #region Bug5456 + SaveChanges(); - [ConditionalFact] - public virtual void Repro5456_include_group_join_is_per_query_context() - { - using (CreateDatabase5456()) - { - Parallel.For( - 0, 10, i => + Contacts.AddRange( + new ServiceOperatorContact6986 { - using var ctx = new MyContext5456(_options); - var result = ctx.Posts.Where(x => x.Blog.Id > 1).Include(x => x.Blog).ToList(); - - Assert.Equal(198, result.Count); - }); + UserName = "service.operator@esoterix.co.uk", + ServiceOperator6986 = ServiceOperators.OrderBy(o => o.Id).First() + }, + new EmployerContact6986 + { + UserName = "uwe@esoterix.co.uk", + Employer6986 = Employers.OrderBy(e => e.Id).First(e => e.Name == "UWE") + }, + new EmployerContact6986 + { + UserName = "hp@esoterix.co.uk", + Employer6986 = Employers.OrderBy(e => e.Id).First(e => e.Name == "Hewlett Packard") + }, + new Contact6986 { UserName = "noroles@esoterix.co.uk" }); + SaveChanges(); } - } - [ConditionalFact] - public virtual async Task Repro5456_include_group_join_is_per_query_context_async() - { - using (CreateDatabase5456()) + public class EmployerContact6986 : Contact6986 { - await Task.WhenAll( - Enumerable.Range(0, 10) - .Select( - async i => - { - using var ctx = new MyContext5456(_options); - var result = await ctx.Posts.Where(x => x.Blog.Id > 1).Include(x => x.Blog).ToListAsync(); - - Assert.Equal(198, result.Count); - })); + [Required] + public Employer6986 Employer6986 { get; set; } } - } - [ConditionalFact] - public virtual void Repro5456_multiple_include_group_join_is_per_query_context() - { - using (CreateDatabase5456()) + public class ServiceOperatorContact6986 : Contact6986 { - Parallel.For( - 0, 10, i => - { - using var ctx = new MyContext5456(_options); - var result = ctx.Posts.Where(x => x.Blog.Id > 1).Include(x => x.Blog).Include(x => x.Comments).ToList(); + [Required] + public ServiceOperator6986 ServiceOperator6986 { get; set; } + } - Assert.Equal(198, result.Count); - }); + public class Contact6986 + { + public int Id { get; set; } + public string UserName { get; set; } + public bool IsPrimary { get; set; } } - } - [ConditionalFact] - public virtual async Task Repro5456_multiple_include_group_join_is_per_query_context_async() - { - using (CreateDatabase5456()) + public class Employer6986 { - await Task.WhenAll( - Enumerable.Range(0, 10) - .Select( - async i => - { - using var ctx = new MyContext5456(_options); - var result = await ctx.Posts.Where(x => x.Blog.Id > 1).Include(x => x.Blog).Include(x => x.Comments) - .ToListAsync(); + public int Id { get; set; } + public string Name { get; set; } + public List Contacts { get; set; } + } - Assert.Equal(198, result.Count); - })); + public class ServiceOperator6986 + { + public int Id { get; set; } + public List Contacts { get; set; } } } + #endregion + + #region Issue5456 + [ConditionalFact] - public virtual void Repro5456_multi_level_include_group_join_is_per_query_context() + public virtual async Task Repro5456_include_group_join_is_per_query_context() { - using (CreateDatabase5456()) - { - Parallel.For( - 0, 10, i => - { - using var ctx = new MyContext5456(_options); - var result = ctx.Posts.Where(x => x.Blog.Id > 1).Include(x => x.Blog).ThenInclude(b => b.Author).ToList(); + var contextFactory = await InitializeAsync(seed: c => c.Seed()); - Assert.Equal(198, result.Count); - }); - } + Parallel.For( + 0, 10, i => + { + using var ctx = contextFactory.CreateContext(); + var result = ctx.Posts.Where(x => x.Blog.Id > 1).Include(x => x.Blog).ToList(); + + Assert.Equal(198, result.Count); + }); + + Parallel.For( + 0, 10, i => + { + using var ctx = contextFactory.CreateContext(); + var result = ctx.Posts.Where(x => x.Blog.Id > 1).Include(x => x.Blog).Include(x => x.Comments).ToList(); + + Assert.Equal(198, result.Count); + }); + + Parallel.For( + 0, 10, i => + { + using var ctx = contextFactory.CreateContext(); + var result = ctx.Posts.Where(x => x.Blog.Id > 1).Include(x => x.Blog).ThenInclude(b => b.Author).ToList(); + + Assert.Equal(198, result.Count); + }); } [ConditionalFact] - public virtual async Task Repro5456_multi_level_include_group_join_is_per_query_context_async() + public virtual async Task Repro5456_include_group_join_is_per_query_context_async() { - using (CreateDatabase5456()) - { - await Task.WhenAll( - Enumerable.Range(0, 10) - .Select( - async i => - { - using var ctx = new MyContext5456(_options); - var result = await ctx.Posts.Where(x => x.Blog.Id > 1).Include(x => x.Blog).ThenInclude(b => b.Author) - .ToListAsync(); + var contextFactory = await InitializeAsync(seed: c => c.Seed()); - Assert.Equal(198, result.Count); - })); - } - } + await Task.WhenAll( + Enumerable.Range(0, 10) + .Select( + async i => + { + using var ctx = contextFactory.CreateContext(); + var result = await ctx.Posts.Where(x => x.Blog.Id > 1).Include(x => x.Blog).ToListAsync(); - private SqlServerTestStore CreateDatabase5456() - { - return CreateTestStore( - () => new MyContext5456(_options), - context => - { - for (var i = 0; i < 100; i++) - { - context.Add( - new Blog5456 - { - Posts = new List - { - new Post5456 { Comments = new List { new Comment5456(), new Comment5456() } }, - new Post5456() - }, - Author = new Author5456() - }); - } + Assert.Equal(198, result.Count); + })); - context.SaveChanges(); - }); + await Task.WhenAll( + Enumerable.Range(0, 10) + .Select( + async i => + { + using var ctx = contextFactory.CreateContext(); + var result = await ctx.Posts.Where(x => x.Blog.Id > 1).Include(x => x.Blog).Include(x => x.Comments) + .ToListAsync(); + + Assert.Equal(198, result.Count); + })); + + await Task.WhenAll( + Enumerable.Range(0, 10) + .Select( + async i => + { + using var ctx = contextFactory.CreateContext(); + var result = await ctx.Posts.Where(x => x.Blog.Id > 1).Include(x => x.Blog).ThenInclude(b => b.Author) + .ToListAsync(); + + Assert.Equal(198, result.Count); + })); } - private class MyContext5456 : DbContext + protected class MyContext5456 : DbContext { public MyContext5456(DbContextOptions options) : base(options) @@ -1681,67 +1519,78 @@ public MyContext5456(DbContextOptions options) public DbSet Posts { get; set; } public DbSet Comments { get; set; } public DbSet Authors { get; set; } - } - private class Blog5456 - { - public int Id { get; set; } - public List Posts { get; set; } - public Author5456 Author { get; set; } - } + public void Seed() + { + for (var i = 0; i < 100; i++) + { + Add( + new Blog5456 + { + Posts = new List + { + new Post5456 { Comments = new List { new Comment5456(), new Comment5456() } }, + new Post5456() + }, + Author = new Author5456() + }); + } - private class Author5456 - { - public int Id { get; set; } - public List Blogs { get; set; } - } + SaveChanges(); + } - private class Post5456 - { - public int Id { get; set; } - public Blog5456 Blog { get; set; } - public List Comments { get; set; } - } + public class Blog5456 + { + public int Id { get; set; } + public List Posts { get; set; } + public Author5456 Author { get; set; } + } - private class Comment5456 - { - public int Id { get; set; } - public Post5456 Blog { get; set; } + public class Author5456 + { + public int Id { get; set; } + public List Blogs { get; set; } + } + + public class Post5456 + { + public int Id { get; set; } + public Blog5456 Blog { get; set; } + public List Comments { get; set; } + } + + public class Comment5456 + { + public int Id { get; set; } + public Post5456 Blog { get; set; } + } } #endregion - #region Bug7359 + #region Issue7359 [ConditionalFact] - public virtual void Discriminator_type_is_handled_correctly_in_materialization_bug_7359() + public virtual async Task Discriminator_type_is_handled_correctly() { - using (CreateDatabase7359()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var ctx = contextFactory.CreateContext()) { - using var ctx = new MyContext7359(_options); - var query = ctx.Products.OfType().ToList(); + var query = ctx.Products.OfType().ToList(); Assert.Single(query); } - } - [ConditionalFact] - public virtual void Discriminator_type_is_handled_correctly_with_is_operator_bug_7359() - { - using (CreateDatabase7359()) + using (var ctx = contextFactory.CreateContext()) { - using var ctx = new MyContext7359(_options); - var query = ctx.Products.Where(p => p is SpecialProduct).ToList(); + var query = ctx.Products.Where(p => p is MyContext7359.SpecialProduct).ToList(); Assert.Single(query); } } - private class SpecialProduct : Product - { - } - - private class MyContext7359 : DbContext + protected class MyContext7359 : DbContext { public MyContext7359(DbContextOptions options) : base(options) @@ -1758,58 +1607,41 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasValue(0) .HasValue(1); } - } - private SqlServerTestStore CreateDatabase7359() - { - return CreateTestStore( - () => new MyContext7359(_options), - context => - { - context.Add( - new Product { Name = "Product1" }); - context.Add( - new SpecialProduct { Name = "SpecialProduct" }); - context.SaveChanges(); - }); - } + public void Seed() + { + Add(new Product { Name = "Product1" }); + Add(new SpecialProduct { Name = "SpecialProduct" }); + SaveChanges(); + } - #endregion + public class Product + { + public int Id { get; set; } - #region Bug7312 + public string Name { get; set; } + } - [ConditionalFact] - public virtual void Reference_include_on_derived_type_with_sibling_works_bug_7312() - { - using (CreateDatabase7312()) + public class SpecialProduct : Product { - using var context = new MyContext7312(_options); - var query = context.Proposal.OfType().Include(l => l.LeaveType).ToList(); - - Assert.Single(query); } } - private class Proposal7312 - { - public int Id { get; set; } - } + #endregion - private class ProposalCustom7312 : Proposal7312 - { - public string Name { get; set; } - } + #region Issue7312 - private class ProposalLeave7312 : Proposal7312 + [ConditionalFact] + public virtual async Task Reference_include_on_derived_type_with_sibling_works_Issue_7312() { - public DateTime LeaveStart { get; set; } - public virtual ProposalLeaveType7312 LeaveType { get; set; } - } + var contextFactory = await InitializeAsync(seed: c => c.Seed()); - private class ProposalLeaveType7312 - { - public int Id { get; set; } - public ICollection ProposalLeaves { get; set; } + using (var context = contextFactory.CreateContext()) + { + var query = context.Proposal.OfType().Include(l => l.LeaveType).ToList(); + + Assert.Single(query); + } } private class MyContext7312 : DbContext @@ -1822,52 +1654,55 @@ public MyContext7312(DbContextOptions options) public DbSet Proposal { get; set; } public DbSet ProposalCustoms { get; set; } public DbSet ProposalLeaves { get; set; } - } - private SqlServerTestStore CreateDatabase7312() - { - return CreateTestStore( - () => new MyContext7312(_options), - context => - { - context.AddRange( - new Proposal7312(), - new ProposalCustom7312 { Name = "CustomProposal" }, - new ProposalLeave7312 { LeaveStart = DateTime.Now, LeaveType = new ProposalLeaveType7312() } - ); - context.SaveChanges(); - }); - } + public void Seed() + { + AddRange( + new Proposal7312(), + new ProposalCustom7312 { Name = "CustomProposal" }, + new ProposalLeave7312 { LeaveStart = DateTime.Now, LeaveType = new ProposalLeaveType7312() } + ); + SaveChanges(); + } - #endregion + public class Proposal7312 + { + public int Id { get; set; } + } - #region Bug8282 + public class ProposalCustom7312 : Proposal7312 + { + public string Name { get; set; } + } - [ConditionalFact] - public virtual void Entity_passed_to_DTO_constructor_works() - { - using (CreateDatabase8282()) + public class ProposalLeave7312 : Proposal7312 { - using var context = new MyContext8282(_options); - var query = context.Entity.Select(e => new EntityDto8282(e)).ToList(); + public DateTime LeaveStart { get; set; } + public virtual ProposalLeaveType7312 LeaveType { get; set; } + } - Assert.Single(query); + public class ProposalLeaveType7312 + { + public int Id { get; set; } + public ICollection ProposalLeaves { get; set; } } } - private class Entity8282 - { - public int Id { get; set; } - } + #endregion - private class EntityDto8282 + #region Issue8282 + + [ConditionalFact] + public virtual async Task Entity_passed_to_DTO_constructor_works() { - public EntityDto8282(Entity8282 entity) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - Id = entity.Id; - } + var query = context.Entity.Select(e => new MyContext8282.EntityDto8282(e)).ToList(); - public int Id { get; } + Assert.Single(query); + } } private class MyContext8282 : DbContext @@ -1878,32 +1713,41 @@ public MyContext8282(DbContextOptions options) } public DbSet Entity { get; set; } - } - private SqlServerTestStore CreateDatabase8282() - { - return CreateTestStore( - () => new MyContext8282(_options), - context => + public void Seed() + { + AddRange(new Entity8282()); + SaveChanges(); + } + + public class Entity8282 + { + public int Id { get; set; } + } + + public class EntityDto8282 + { + public EntityDto8282(Entity8282 entity) { - context.AddRange( - new Entity8282() - ); - context.SaveChanges(); - }); + Id = entity.Id; + } + + public int Id { get; } + } } #endregion - #region Bug8538 + #region Issue8538 [ConditionalFact] - public virtual void Enum_has_flag_applies_explicit_cast_for_long_constant() + public virtual async Task Enum_has_flag_applies_explicit_cast_for_constant() { - using (CreateDatabase8538()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext8538(_options); - var query = context.Entity.Where(e => e.Permission.HasFlag(Permission.READ_WRITE)).ToList(); + var query = context.Entity.Where(e => e.Permission.HasFlag(MyContext8538.Permission.READ_WRITE)).ToList(); Assert.Single(query); @@ -1911,92 +1755,53 @@ public virtual void Enum_has_flag_applies_explicit_cast_for_long_constant() @"SELECT [e].[Id], [e].[Permission], [e].[PermissionByte], [e].[PermissionShort] FROM [Entity] AS [e] WHERE ([e].[Permission] & CAST(17179869184 AS bigint)) = CAST(17179869184 AS bigint)"); + ClearLog(); } - } - [ConditionalFact] - public virtual void Enum_has_flag_does_not_apply_explicit_cast_for_non_constant() - { - using (CreateDatabase8538()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext8538(_options); - var query = context.Entity.Where(e => e.Permission.HasFlag(e.Permission)).ToList(); + var query = context.Entity.Where(e => e.PermissionShort.HasFlag(MyContext8538.PermissionShort.READ_WRITE)).ToList(); - Assert.Equal(3, query.Count); + Assert.Single(query); AssertSql( @"SELECT [e].[Id], [e].[Permission], [e].[PermissionByte], [e].[PermissionShort] FROM [Entity] AS [e] -WHERE ([e].[Permission] & [e].[Permission]) = [e].[Permission]"); +WHERE ([e].[PermissionShort] & CAST(4 AS smallint)) = CAST(4 AS smallint)"); } } [ConditionalFact] - public virtual void Byte_enum_has_flag_does_not_apply_explicit_cast_for_non_constant() + public virtual async Task Enum_has_flag_does_not_apply_explicit_cast_for_non_constant() { - using (CreateDatabase8538()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext8538(_options); - var query = context.Entity.Where(e => e.PermissionByte.HasFlag(e.PermissionByte)).ToList(); + var query = context.Entity.Where(e => e.Permission.HasFlag(e.Permission)).ToList(); Assert.Equal(3, query.Count); AssertSql( @"SELECT [e].[Id], [e].[Permission], [e].[PermissionByte], [e].[PermissionShort] FROM [Entity] AS [e] -WHERE ([e].[PermissionByte] & [e].[PermissionByte]) = [e].[PermissionByte]"); +WHERE ([e].[Permission] & [e].[Permission]) = [e].[Permission]"); + ClearLog(); } - } - [ConditionalFact] - public virtual void Enum_has_flag_applies_explicit_cast_for_short_constant() - { - using (CreateDatabase8538()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext8538(_options); - var query = context.Entity.Where(e => e.PermissionShort.HasFlag(PermissionShort.READ_WRITE)).ToList(); + var query = context.Entity.Where(e => e.PermissionByte.HasFlag(e.PermissionByte)).ToList(); - Assert.Single(query); + Assert.Equal(3, query.Count); AssertSql( @"SELECT [e].[Id], [e].[Permission], [e].[PermissionByte], [e].[PermissionShort] FROM [Entity] AS [e] -WHERE ([e].[PermissionShort] & CAST(4 AS smallint)) = CAST(4 AS smallint)"); +WHERE ([e].[PermissionByte] & [e].[PermissionByte]) = [e].[PermissionByte]"); } } - private class Entity8538 - { - public int Id { get; set; } - public Permission Permission { get; set; } - public PermissionByte PermissionByte { get; set; } - public PermissionShort PermissionShort { get; set; } - } - - [Flags] - private enum PermissionByte : byte - { - NONE = 1, - READ_ONLY = 2, - READ_WRITE = 4 - } - - [Flags] - private enum PermissionShort : short - { - NONE = 1, - READ_ONLY = 2, - READ_WRITE = 4 - } - - [Flags] - private enum Permission : long - { - NONE = 0x01, - READ_ONLY = 0x02, - READ_WRITE = 0x400000000 // 36 bits - } - private class MyContext8538 : DbContext { public MyContext8538(DbContextOptions options) @@ -2005,50 +1810,77 @@ public MyContext8538(DbContextOptions options) } public DbSet Entity { get; set; } - } - private SqlServerTestStore CreateDatabase8538() - { - return CreateTestStore( - () => new MyContext8538(_options), - context => - { - context.AddRange( - new Entity8538 - { - Permission = Permission.NONE, - PermissionByte = PermissionByte.NONE, - PermissionShort = PermissionShort.NONE - }, - new Entity8538 - { - Permission = Permission.READ_ONLY, - PermissionByte = PermissionByte.READ_ONLY, - PermissionShort = PermissionShort.READ_ONLY - }, - new Entity8538 - { - Permission = Permission.READ_WRITE, - PermissionByte = PermissionByte.READ_WRITE, - PermissionShort = PermissionShort.READ_WRITE - } - ); - context.SaveChanges(); + public void Seed() + { + AddRange( + new Entity8538 + { + Permission = Permission.NONE, + PermissionByte = PermissionByte.NONE, + PermissionShort = PermissionShort.NONE + }, + new Entity8538 + { + Permission = Permission.READ_ONLY, + PermissionByte = PermissionByte.READ_ONLY, + PermissionShort = PermissionShort.READ_ONLY + }, + new Entity8538 + { + Permission = Permission.READ_WRITE, + PermissionByte = PermissionByte.READ_WRITE, + PermissionShort = PermissionShort.READ_WRITE + } + ); - ClearLog(); - }); + SaveChanges(); + } + + public class Entity8538 + { + public int Id { get; set; } + public Permission Permission { get; set; } + public PermissionByte PermissionByte { get; set; } + public PermissionShort PermissionShort { get; set; } + } + + [Flags] + public enum PermissionByte : byte + { + NONE = 1, + READ_ONLY = 2, + READ_WRITE = 4 + } + + [Flags] + public enum PermissionShort : short + { + NONE = 1, + READ_ONLY = 2, + READ_WRITE = 4 + } + + [Flags] + public enum Permission : long + { + NONE = 0x01, + READ_ONLY = 0x02, + READ_WRITE = 0x400000000 // 36 bits + } } #endregion - #region Bug8909 + #region Issue8909 [ConditionalFact] - public virtual void Variable_from_closure_is_parametrized() + public virtual async Task Variable_from_closure_is_parametrized() { - using (CreateDatabase8909()) + var contextFactory = await InitializeAsync(); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext8909(_options); context.Cache.Compact(1); var id = 1; @@ -2071,20 +1903,16 @@ FROM [Entities] AS [e] SELECT [e].[Id], [e].[Name] FROM [Entities] AS [e] WHERE [e].[Id] = @__id_0"); + ClearLog(); } - } - [ConditionalFact] - public virtual void Variable_from_nested_closure_is_parametrized() - { - using (CreateDatabase8909()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext8909(_options); context.Cache.Compact(1); var id = 0; // ReSharper disable once AccessToModifiedClosure - Expression> whereExpression = c => c.Id == id; + Expression> whereExpression = c => c.Id == id; id = 1; context.Entities.Where(whereExpression).ToList(); @@ -2106,21 +1934,17 @@ FROM [Entities] AS [e] SELECT [e].[Id], [e].[Name] FROM [Entities] AS [e] WHERE [e].[Id] = @__id_0"); + ClearLog(); } - } - [ConditionalFact] - public virtual void Variable_from_multi_level_nested_closure_is_parametrized() - { - using (CreateDatabase8909()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext8909(_options); context.Cache.Compact(1); var id = 0; // ReSharper disable once AccessToModifiedClosure - Expression> whereExpression = c => c.Id == id; - Expression> containsExpression = + Expression> whereExpression = c => c.Id == id; + Expression> containsExpression = c => context.Entities.Where(whereExpression).Select(e => e.Id).Contains(c.Id); id = 1; @@ -2153,11 +1977,12 @@ FROM [Entities] AS [e0] } [ConditionalFact] - public virtual void Relational_command_cache_creates_new_entry_when_parameter_nullability_changes() + public virtual async Task Relational_command_cache_creates_new_entry_when_parameter_nullability_changes() { - using (CreateDatabase8909()) + var contextFactory = await InitializeAsync(); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext8909(_options); context.Cache.Compact(1); var name = "A"; @@ -2183,24 +2008,25 @@ FROM [Entities] AS [e] } [ConditionalFact] - public virtual void Query_cache_entries_are_evicted_as_necessary() + public virtual async Task Query_cache_entries_are_evicted_as_necessary() { - using (CreateDatabase8909()) + var contextFactory = await InitializeAsync(); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext8909(_options); context.Cache.Compact(1); Assert.Equal(0, context.Cache.Count); - var entityParam = Expression.Parameter(typeof(Entity8909), "e"); - var idPropertyInfo = context.Model.FindEntityType((typeof(Entity8909))) - .FindProperty(nameof(Entity8909.Id)) + var entityParam = Expression.Parameter(typeof(MyContext8909.Entity8909), "e"); + var idPropertyInfo = context.Model.FindEntityType((typeof(MyContext8909.Entity8909))) + .FindProperty(nameof(MyContext8909.Entity8909.Id)) .PropertyInfo; for (var i = 0; i < 1100; i++) { var conditionBody = Expression.Equal( Expression.MakeMemberAccess(entityParam, idPropertyInfo), Expression.Constant(i)); - var whereExpression = Expression.Lambda>(conditionBody, entityParam); + var whereExpression = Expression.Lambda>(conditionBody, entityParam); context.Entities.Where(whereExpression).GetEnumerator(); } @@ -2209,19 +2035,21 @@ public virtual void Query_cache_entries_are_evicted_as_necessary() } [ConditionalFact] - public virtual void Explicitly_compiled_query_does_not_add_cache_entry() + public virtual async Task Explicitly_compiled_query_does_not_add_cache_entry() { - var parameter = Expression.Parameter(typeof(Entity8909)); - var predicate = Expression.Lambda>( + var parameter = Expression.Parameter(typeof(MyContext8909.Entity8909)); + var predicate = Expression.Lambda>( Expression.MakeBinary( ExpressionType.Equal, Expression.PropertyOrField(parameter, "Id"), Expression.Constant(1)), parameter); - var query = EF.CompileQuery((MyContext8909 context) => context.Set().SingleOrDefault(predicate)); - using (CreateDatabase8909()) + var query = EF.CompileQuery((MyContext8909 context) => context.Set().SingleOrDefault(predicate)); + + var contextFactory = await InitializeAsync(); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext8909(_options); context.Cache.Compact(1); Assert.Equal(0, context.Cache.Count); @@ -2232,14 +2060,7 @@ public virtual void Explicitly_compiled_query_does_not_add_cache_entry() } } - private SqlServerTestStore CreateDatabase8909() - { - return CreateTestStore( - () => new MyContext8909(_options), - context => ClearLog()); - } - - private class MyContext8909 : DbContext + protected class MyContext8909 : DbContext { public MyContext8909(DbContextOptions options) : base(options) @@ -2259,24 +2080,25 @@ public MemoryCache Cache ?.GetValue(compiledQueryCache); } } - } - private class Entity8909 - { - public int Id { get; set; } - public string Name { get; set; } + public class Entity8909 + { + public int Id { get; set; } + public string Name { get; set; } + } } #endregion - #region Bug9202/9210 + #region Issue9202/9210 [ConditionalFact] - public void Include_collection_for_entity_with_owned_type_works() + public async Task Include_collection_for_entity_with_owned_type_works() { - using (CreateDatabase9202()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext9202(_options); var query = context.Movies.Include(m => m.Cast); var result = query.ToList(); @@ -2290,15 +2112,11 @@ public void Include_collection_for_entity_with_owned_type_works() FROM [Movies] AS [m] LEFT JOIN [Actors] AS [a] ON [m].[Id] = [a].[Movie9202Id] ORDER BY [m].[Id], [a].[Id]"); + ClearLog(); } - } - [ConditionalFact] - public void Include_collection_for_entity_with_owned_type_works_string() - { - using (CreateDatabase9202()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext9202(_options); var query = context.Movies.Include("Cast"); var result = query.ToList(); @@ -2315,35 +2133,7 @@ FROM [Movies] AS [m] } } - private SqlServerTestStore CreateDatabase9202() - { - return CreateTestStore( - () => new MyContext9202(_options), - context => - { - var av = new Actor9202 { Name = "Alicia Vikander", Details = new Details9202 { Info = "Best actor ever made" } }; - var oi = new Actor9202 { Name = "Oscar Isaac", Details = new Details9202 { Info = "Best actor ever made" } }; - var dg = new Actor9202 { Name = "Domhnall Gleeson", Details = new Details9202 { Info = "Best actor ever made" } }; - var em = new Movie9202 - { - Title = "Ex Machina", - Cast = new List - { - av, - oi, - dg - }, - Details = new Details9202 { Info = "Best movie ever made" } - }; - context.Actors.AddRange(av, oi, dg); - context.Movies.Add(em); - context.SaveChanges(); - - ClearLog(); - }); - } - - private class MyContext9202 : DbContext + protected class MyContext9202 : DbContext { public MyContext9202(DbContextOptions options) : base(options) @@ -2359,40 +2149,64 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity().OwnsOne(m => m.Details); modelBuilder.Entity().OwnsOne(m => m.Details); } - } - private class Movie9202 - { - public int Id { get; set; } - public string Title { get; set; } + public void Seed() + { - public List Cast { get; set; } + var av = new Actor9202 { Name = "Alicia Vikander", Details = new Details9202 { Info = "Best actor ever made" } }; + var oi = new Actor9202 { Name = "Oscar Isaac", Details = new Details9202 { Info = "Best actor ever made" } }; + var dg = new Actor9202 { Name = "Domhnall Gleeson", Details = new Details9202 { Info = "Best actor ever made" } }; + var em = new Movie9202 + { + Title = "Ex Machina", + Cast = new List + { + av, + oi, + dg + }, + Details = new Details9202 { Info = "Best movie ever made" } + }; - public Details9202 Details { get; set; } - } + Actors.AddRange(av, oi, dg); + Movies.Add(em); + SaveChanges(); + } - private class Actor9202 - { - public int Id { get; set; } - public string Name { get; set; } - public Details9202 Details { get; set; } - } + public class Movie9202 + { + public int Id { get; set; } + public string Title { get; set; } - private class Details9202 - { - public string Info { get; set; } + public List Cast { get; set; } + + public Details9202 Details { get; set; } + } + + public class Actor9202 + { + public int Id { get; set; } + public string Name { get; set; } + public Details9202 Details { get; set; } + } + + public class Details9202 + { + public string Info { get; set; } + } } #endregion - #region Bug9214 + #region Issue9214 [ConditionalFact] - public void Default_schema_applied_when_no_function_schema() + public async Task Default_schema_applied_when_no_function_schema() { - using (CreateDatabase9214()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext9214(_options); var result = context.Widgets.Where(w => w.Val == 1).Select(w => MyContext9214.AddOne(w.Val)).Single(); Assert.Equal(2, result); @@ -2401,15 +2215,11 @@ public void Default_schema_applied_when_no_function_schema() @"SELECT TOP(2) [foo].[AddOne]([w].[Val]) FROM [foo].[Widgets] AS [w] WHERE [w].[Val] = 1"); + ClearLog(); } - } - [ConditionalFact] - public void Default_schema_function_schema_overrides() - { - using (CreateDatabase9214()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext9214(_options); var result = context.Widgets.Where(w => w.Val == 1).Select(w => MyContext9214.AddTwo(w.Val)).Single(); Assert.Equal(3, result); @@ -2421,39 +2231,7 @@ FROM [foo].[Widgets] AS [w] } } - private SqlServerTestStore CreateDatabase9214() - { - return CreateTestStore( - () => new MyContext9214(_options), - context => - { - var w1 = new Widget9214 { Val = 1 }; - var w2 = new Widget9214 { Val = 2 }; - var w3 = new Widget9214 { Val = 3 }; - context.Widgets.AddRange(w1, w2, w3); - context.SaveChanges(); - - context.Database.ExecuteSqlRaw( - @"CREATE FUNCTION foo.AddOne (@num int) - RETURNS int - AS - BEGIN - return @num + 1 ; - END"); - - context.Database.ExecuteSqlRaw( - @"CREATE FUNCTION dbo.AddTwo (@num int) - RETURNS int - AS - BEGIN - return @num + 2 ; - END"); - - ClearLog(); - }); - } - - private class MyContext9214 : DbContext + protected class MyContext9214 : DbContext { public DbSet Widgets { get; set; } @@ -2488,24 +2266,50 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.HasDbFunction(typeof(MyContext9214).GetMethod(nameof(AddOne))); modelBuilder.HasDbFunction(typeof(MyContext9214).GetMethod(nameof(AddTwo))).HasSchema("dbo"); } - } - private class Widget9214 - { - public int Id { get; set; } - public int Val { get; set; } + public void Seed() + { + var w1 = new Widget9214 { Val = 1 }; + var w2 = new Widget9214 { Val = 2 }; + var w3 = new Widget9214 { Val = 3 }; + Widgets.AddRange(w1, w2, w3); + SaveChanges(); + + Database.ExecuteSqlRaw( + @"CREATE FUNCTION foo.AddOne (@num int) + RETURNS int + AS + BEGIN + return @num + 1 ; + END"); + + Database.ExecuteSqlRaw( + @"CREATE FUNCTION dbo.AddTwo (@num int) + RETURNS int + AS + BEGIN + return @num + 2 ; + END"); + } + + public class Widget9214 + { + public int Id { get; set; } + public int Val { get; set; } + } } #endregion - #region Bug9277 + #region Issue9277 [ConditionalFact] - public virtual void From_sql_gets_value_of_out_parameter_in_stored_procedure() + public virtual async Task From_sql_gets_value_of_out_parameter_in_stored_procedure() { - using (CreateDatabase9277()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext9277(_options); var valueParam = new SqlParameter { ParameterName = "Value", @@ -2527,14 +2331,19 @@ public virtual void From_sql_gets_value_of_out_parameter_in_stored_procedure() } } - private SqlServerTestStore CreateDatabase9277() + protected class MyContext9277 : DbContext { - return CreateTestStore( - () => new MyContext9277(_options), - context => - { - context.Database.ExecuteSqlRaw( - @"CREATE PROCEDURE [dbo].[GetPersonAndVoteCount] + public MyContext9277(DbContextOptions options) + : base(options) + { + } + + public DbSet Blogs { get; set; } + + public void Seed() + { + Database.ExecuteSqlRaw( + @"CREATE PROCEDURE [dbo].[GetPersonAndVoteCount] ( @id int, @Value int OUTPUT @@ -2549,45 +2358,34 @@ FROM dbo.Blogs WHERE Id = @id; END"); - context.AddRange( - new Blog9277 { SomeValue = 1 }, - new Blog9277 { SomeValue = 2 }, - new Blog9277 { SomeValue = 3 } - ); + AddRange( + new Blog9277 { SomeValue = 1 }, + new Blog9277 { SomeValue = 2 }, + new Blog9277 { SomeValue = 3 } + ); - context.SaveChanges(); + SaveChanges(); + } - ClearLog(); - }); - } - - private class MyContext9277 : DbContext - { - public MyContext9277(DbContextOptions options) - : base(options) + public class Blog9277 { + public int Id { get; set; } + public int SomeValue { get; set; } } - - public DbSet Blogs { get; set; } - } - - private class Blog9277 - { - public int Id { get; set; } - public int SomeValue { get; set; } } #endregion - #region Bug9038 + #region Issue9038 [ConditionalFact] - public virtual async Task Include_collection_optional_reference_collection_9038() + public virtual async Task Include_collection_optional_reference_collection() { - using (CreateDatabase9038()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext9038(_options); - var result = await context.People.OfType() + var result = await context.People.OfType() .Include(m => m.Students) .ThenInclude(m => m.Family) .ThenInclude(m => m.Members) @@ -2596,15 +2394,10 @@ public virtual async Task Include_collection_optional_reference_collection_9038( Assert.Equal(2, result.Count); Assert.True(result.All(r => r.Students.Count > 0)); } - } - [ConditionalFact] - public async Task Include_optional_reference_collection_another_collection() - { - using (CreateDatabase9038()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext9038(_options); - var result = await context.Set() + var result = await context.Set() .Include(m => m.Family.Members) .Include(m => m.Students) .ToListAsync(); @@ -2616,39 +2409,7 @@ public async Task Include_optional_reference_collection_another_collection() } } - private abstract class Person9038 - { - public int Id { get; set; } - - public string Name { get; set; } - - public int? TeacherId { get; set; } - - public PersonFamily9038 Family { get; set; } - } - - private class PersonKid9038 : Person9038 - { - public int Grade { get; set; } - - public PersonTeacher9038 Teacher { get; set; } - } - - private class PersonTeacher9038 : Person9038 - { - public ICollection Students { get; set; } - } - - private class PersonFamily9038 - { - public int Id { get; set; } - - public string LastName { get; set; } - - public ICollection Members { get; set; } - } - - private class MyContext9038 : DbContext + protected class MyContext9038 : DbContext { public MyContext9038(DbContextOptions options) : base(options) @@ -2679,24 +2440,20 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .OnDelete(DeleteBehavior.Restrict); }); } - } - private SqlServerTestStore CreateDatabase9038() - { - return CreateTestStore( - () => new MyContext9038(_options), - context => - { - var famalies = new List + public void Seed() + { + + var famalies = new List { new PersonFamily9038 { LastName = "Garrison" }, new PersonFamily9038 { LastName = "Cartman" } }; - var teachers = new List + var teachers = new List { new PersonTeacher9038 { Name = "Ms. Frizzle" }, new PersonTeacher9038 { Name = "Mr. Garrison", Family = famalies[0] } }; - var students = new List + var students = new List { new PersonKid9038 { @@ -2713,128 +2470,55 @@ private SqlServerTestStore CreateDatabase9038() } }; - context.People.AddRange(teachers); - context.People.AddRange(students); - context.SaveChanges(); - - ClearLog(); - }); - } - - #endregion - - #region Bug9735 + People.AddRange(teachers); + People.AddRange(students); + SaveChanges(); + } - [ConditionalFact] - // TODO: Convert to test in IncludeTestBase once issue #9742 is fixed - public virtual void Repro9735() - { - using (CreateDatabase9735()) + public abstract class Person9038 { - using var context = new MyContext9735(_options); - var result = context.Customers - .Include(b => b.Orders) - .OrderBy(b => b.Address.Id > 0) - .ThenBy(b => b.CustomerDetails != null ? b.CustomerDetails.Name : string.Empty) - .Take(2) - .ToList(); + public int Id { get; set; } - Assert.Single(result); + public string Name { get; set; } - AssertSql( - @"@__p_0='2' + public int? TeacherId { get; set; } -SELECT [t].[Id], [t].[AddressId], [t].[CustomerDetailsId], [t].[Name], [t].[Id0], [t].[Id1], [o].[Id], [o].[CustomerId], [o].[Name] -FROM ( - SELECT TOP(@__p_0) [c].[Id], [c].[AddressId], [c].[CustomerDetailsId], [c].[Name], [a].[Id] AS [Id0], [c0].[Id] AS [Id1], CASE - WHEN [a].[Id] > 0 THEN CAST(1 AS bit) - ELSE CAST(0 AS bit) - END AS [c], CASE - WHEN [c0].[Id] IS NOT NULL THEN [c0].[Name] - ELSE N'' - END AS [c0] - FROM [Customers] AS [c] - INNER JOIN [Address9735] AS [a] ON [c].[AddressId] = [a].[Id] - LEFT JOIN [CustomerDetails9735] AS [c0] ON [c].[CustomerDetailsId] = [c0].[Id] - ORDER BY CASE - WHEN [a].[Id] > 0 THEN CAST(1 AS bit) - ELSE CAST(0 AS bit) - END, CASE - WHEN [c0].[Id] IS NOT NULL THEN [c0].[Name] - ELSE N'' - END -) AS [t] -LEFT JOIN [Order9735] AS [o] ON [t].[Id] = [o].[CustomerId] -ORDER BY [t].[c], [t].[c0], [t].[Id], [t].[Id0], [t].[Id1], [o].[Id]"); + public PersonFamily9038 Family { get; set; } } - } - - private class Address9735 - { - public int Id { get; set; } - public string Name { get; set; } - } - - private class Customer9735 - { - public int Id { get; set; } - public string Name { get; set; } - public int AddressId { get; set; } - public virtual Address9735 Address { get; set; } - public virtual List Orders { get; set; } - public virtual CustomerDetails9735 CustomerDetails { get; set; } - } - private class Order9735 - { - public int Id { get; set; } - public string Name { get; set; } - public int CustomerId { get; set; } - public virtual Customer9735 Customer { get; set; } - } + public class PersonKid9038 : Person9038 + { + public int Grade { get; set; } - private class CustomerDetails9735 - { - public int Id { get; set; } - public string Name { get; set; } - } + public PersonTeacher9038 Teacher { get; set; } + } - private class MyContext9735 : DbContext - { - public MyContext9735(DbContextOptions options) - : base(options) + public class PersonTeacher9038 : Person9038 { + public ICollection Students { get; set; } } - public DbSet Customers { get; set; } - } + public class PersonFamily9038 + { + public int Id { get; set; } - private SqlServerTestStore CreateDatabase9735() - { - return CreateTestStore( - () => new MyContext9735(_options), - context => - { - context.AddRange( - new Address9735 { Name = "An A" }, - new Customer9735 { Name = "A B", AddressId = 1 } - ); - context.SaveChanges(); + public string LastName { get; set; } - ClearLog(); - }); + public ICollection Members { get; set; } + } } #endregion - #region Bug9468 + #region Issue9468 [ConditionalFact] - public virtual void Conditional_expression_with_conditions_does_not_collapse_if_nullable_bool() + public virtual async Task Conditional_expression_with_conditions_does_not_collapse_if_nullable_bool() { - using (CreateDatabase9468()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext9468(_options); var query = context.Carts.Select( t => new { Processing = t.Configuration != null ? !t.Configuration.Processed : (bool?)null }).ToList(); @@ -2855,25 +2539,7 @@ FROM [Carts] AS [c] } } - private SqlServerTestStore CreateDatabase9468() - { - return CreateTestStore( - () => new MyContext9468(_options), - context => - { - context.AddRange( - new Cart9468(), - new Cart9468 { Configuration = new Configuration9468 { Processed = true } }, - new Cart9468 { Configuration = new Configuration9468() } - ); - - context.SaveChanges(); - - ClearLog(); - }); - } - - private class MyContext9468 : DbContext + protected class MyContext9468 : DbContext { public MyContext9468(DbContextOptions options) : base(options) @@ -2881,31 +2547,43 @@ public MyContext9468(DbContextOptions options) } public DbSet Carts { get; set; } - } - private class Cart9468 - { - public int Id { get; set; } - public int? ConfigurationId { get; set; } - public Configuration9468 Configuration { get; set; } - } + public void Seed() + { + AddRange( + new Cart9468(), + new Cart9468 { Configuration = new Configuration9468 { Processed = true } }, + new Cart9468 { Configuration = new Configuration9468() } + ); - private class Configuration9468 - { - public int Id { get; set; } - public bool Processed { get; set; } + SaveChanges(); + } + + public class Cart9468 + { + public int Id { get; set; } + public int? ConfigurationId { get; set; } + public Configuration9468 Configuration { get; set; } + } + + public class Configuration9468 + { + public int Id { get; set; } + public bool Processed { get; set; } + } } #endregion - #region Bug10635 + #region Issue10635 [ConditionalFact] - public void Include_with_order_by_on_interface_key() + public async Task Include_with_order_by_on_interface_key() { - using (CreateDatabase10635()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext10635(_options); var query = context.Parents.Include(p => p.Children).OrderBy(p => p.Id).ToList(); AssertSql( @@ -2913,15 +2591,11 @@ public void Include_with_order_by_on_interface_key() FROM [Parents] AS [p] LEFT JOIN [Children] AS [c] ON [p].[Id] = [c].[Parent10635Id] ORDER BY [p].[Id], [c].[Id]"); + ClearLog(); } - } - [ConditionalFact] - public void Correlated_collection_with_order_by_on_interface_key() - { - using (CreateDatabase10635()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext10635(_options); var query = context.Parents.OrderBy(p => p.Id).Select(p => p.Children.ToList()).ToList(); AssertSql( @@ -2932,27 +2606,6 @@ FROM [Parents] AS [p] } } - private SqlServerTestStore CreateDatabase10635() - { - return CreateTestStore( - () => new MyContext10635(_options), - context => - { - var c11 = new Child10635 { Name = "Child111" }; - var c12 = new Child10635 { Name = "Child112" }; - var c13 = new Child10635 { Name = "Child113" }; - var c21 = new Child10635 { Name = "Child121" }; - - var p1 = new Parent10635 { Name = "Parent1", Children = new[] { c11, c12, c13 } }; - var p2 = new Parent10635 { Name = "Parent2", Children = new[] { c21 } }; - context.Parents.AddRange(p1, p2); - context.Children.AddRange(c11, c12, c13, c21); - context.SaveChanges(); - - ClearLog(); - }); - } - private class MyContext10635 : DbContext { public MyContext10635(DbContextOptions options) @@ -2962,37 +2615,52 @@ public MyContext10635(DbContextOptions options) public DbSet Parents { get; set; } public DbSet Children { get; set; } - } - private interface IEntity10635 - { - int Id { get; set; } - } + public void Seed() + { + var c11 = new Child10635 { Name = "Child111" }; + var c12 = new Child10635 { Name = "Child112" }; + var c13 = new Child10635 { Name = "Child113" }; + var c21 = new Child10635 { Name = "Child121" }; - private class Parent10635 : IEntity10635 - { - public int Id { get; set; } - public string Name { get; set; } - public virtual ICollection Children { get; set; } - } + var p1 = new Parent10635 { Name = "Parent1", Children = new[] { c11, c12, c13 } }; + var p2 = new Parent10635 { Name = "Parent2", Children = new[] { c21 } }; + Parents.AddRange(p1, p2); + Children.AddRange(c11, c12, c13, c21); + SaveChanges(); + } - private class Child10635 : IEntity10635 - { - public int Id { get; set; } - public string Name { get; set; } - public int ParentId { get; set; } + public interface IEntity10635 + { + int Id { get; set; } + } + + public class Parent10635 : IEntity10635 + { + public int Id { get; set; } + public string Name { get; set; } + public virtual ICollection Children { get; set; } + } + + public class Child10635 : IEntity10635 + { + public int Id { get; set; } + public string Name { get; set; } + public int ParentId { get; set; } + } } #endregion - #region Bug10301 + #region Issue10301 [ConditionalFact] - public virtual void MultiContext_query_filter_test() + public virtual async Task MultiContext_query_filter_test() { - using (CreateDatabase10301()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new FilterContext10301(_options); Assert.Empty(context.Blogs.ToList()); context.Tenant = 1; @@ -3022,25 +2690,7 @@ FROM [Blogs] AS [b] } } - private SqlServerTestStore CreateDatabase10301() - { - return CreateTestStore( - () => new FilterContext10301(_options), - context => - { - context.AddRange( - new Blog10301 { SomeValue = 1 }, - new Blog10301 { SomeValue = 2 }, - new Blog10301 { SomeValue = 2 } - ); - - context.SaveChanges(); - - ClearLog(); - }); - } - - private class FilterContextBase10301 : DbContext + protected class FilterContextBase10301 : DbContext { public int Tenant { get; set; } @@ -3055,15 +2705,26 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity().HasQueryFilter(e => e.SomeValue == Tenant); } - } - private class Blog10301 - { - public int Id { get; set; } - public int SomeValue { get; set; } + public void Seed() + { + AddRange( + new Blog10301 { SomeValue = 1 }, + new Blog10301 { SomeValue = 2 }, + new Blog10301 { SomeValue = 2 } + ); + + SaveChanges(); + } + + public class Blog10301 + { + public int Id { get; set; } + public int SomeValue { get; set; } + } } - private class FilterContext10301 : FilterContextBase10301 + protected class FilterContext10301 : FilterContextBase10301 { public FilterContext10301(DbContextOptions options) : base(options) @@ -3073,18 +2734,19 @@ public FilterContext10301(DbContextOptions options) #endregion - #region Bug11104 + #region Issue11104 [ConditionalFact] - public virtual void QueryBuffer_requirement_is_computed_when_querying_base_type_while_derived_type_has_shadow_prop() + public virtual async Task QueryBuffer_requirement_is_computed_when_querying_base_type_while_derived_type_has_shadow_prop() { - using (CreateDatabase11104()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext11104(_options); var query = context.Bases.ToList(); var derived1 = Assert.Single(query); - Assert.Equal(typeof(Derived1), derived1.GetType()); + Assert.Equal(typeof(MyContext11104.Derived1), derived1.GetType()); AssertSql( @"SELECT [b].[Id], [b].[IsTwo], [b].[MoreStuffId] @@ -3092,23 +2754,7 @@ public virtual void QueryBuffer_requirement_is_computed_when_querying_base_type_ } } - private SqlServerTestStore CreateDatabase11104() - { - return CreateTestStore( - () => new MyContext11104(_options), - context => - { - context.AddRange( - new Derived1 { IsTwo = false } - ); - - context.SaveChanges(); - - ClearLog(); - }); - } - - private class MyContext11104 : DbContext + protected class MyContext11104 : DbContext { public DbSet Bases { get; set; } @@ -3124,40 +2770,51 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasValue(false) .HasValue(true); } - } - private abstract class Base - { - public int Id { get; set; } - public bool IsTwo { get; set; } - } + public void Seed() + { + AddRange( + new Derived1 { IsTwo = false } + ); - private class Derived1 : Base - { - public Stuff MoreStuff { get; set; } - } + SaveChanges(); + } - private class Derived2 : Base - { - } + public abstract class Base + { + public int Id { get; set; } + public bool IsTwo { get; set; } + } - private class Stuff - { - public int Id { get; set; } + public class Derived1 : Base + { + public Stuff MoreStuff { get; set; } + } + + public class Derived2 : Base + { + } + + public class Stuff + { + public int Id { get; set; } + } } #endregion - #region Bug11818_11831 + #region Issue11818_11831 [ConditionalFact] - public virtual void GroupJoin_Anonymous_projection_GroupBy_Aggregate_join_elimination() + public virtual async Task GroupJoin_Anonymous_projection_GroupBy_Aggregate_join_elimination() { - using (CreateDatabase11818()) + var contextFactory = await InitializeAsync(onConfiguring: + o => o.ConfigureWarnings(w => w.Log(CoreEventId.FirstWithoutOrderByAndFilterWarning))); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext11818(_options); - var query = (from e in context.Set() - join a in context.Set() + var query = (from e in context.Set() + join a in context.Set() on e.Id equals a.Id into grouping from a in grouping.DefaultIfEmpty() select new { ename = e.Name, aname = a.Name }) @@ -3166,6 +2823,8 @@ from a in grouping.DefaultIfEmpty() g => new { g.Key, cnt = g.Count() + 5 }) .ToList(); + Assert.Empty(query); + AssertSql( @"SELECT [t2].[AnotherEntity11818_Name] AS [Key], COUNT(*) + 5 AS [cnt] FROM [Table] AS [t] @@ -3176,20 +2835,16 @@ FROM [Table] AS [t0] WHERE [t0].[AnotherEntity11818_Name] IS NOT NULL ) AS [t2] ON [t].[Id] = [t2].[Id] GROUP BY [t2].[AnotherEntity11818_Name]"); + ClearLog(); } - } - [ConditionalFact] - public virtual void GroupJoin_Anonymous_projection_GroupBy_Aggregate_join_elimination_2() - { - using (CreateDatabase11818()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext11818(_options); - var query = (from e in context.Set() - join a in context.Set() + var query = (from e in context.Set() + join a in context.Set() on e.Id equals a.Id into grouping from a in grouping.DefaultIfEmpty() - join m in context.Set() + join m in context.Set() on e.Id equals m.Id into grouping2 from m in grouping2.DefaultIfEmpty() select new { aname = a.Name, mname = m.Name }) @@ -3199,6 +2854,8 @@ from m in grouping2.DefaultIfEmpty() g => new { MyKey = g.Key.aname, cnt = g.Count() + 5 }) .ToList(); + Assert.Empty(query); + AssertSql( @"SELECT [t2].[AnotherEntity11818_Name] AS [MyKey], COUNT(*) + 5 AS [cnt] FROM [Table] AS [t] @@ -3215,48 +2872,45 @@ FROM [Table] AS [t3] WHERE [t3].[MaumarEntity11818_Name] IS NOT NULL ) AS [t5] ON [t].[Id] = [t5].[Id] GROUP BY [t2].[AnotherEntity11818_Name], [t5].[MaumarEntity11818_Name]"); + ClearLog(); } - } - [ConditionalFact(Skip = "Issue #11871")] - public virtual void GroupJoin_Anonymous_projection_GroupBy_Aggregate_join_elimination_4() - { - using (CreateDatabase11818()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext11818(_options); - var query = (from e in context.Set() - join a in context.Set() + var query = (from e in context.Set() + join a in context.Set() on e.Id equals a.Id into grouping from a in grouping.DefaultIfEmpty() - join m in context.Set() + join m in context.Set() on e.Id equals m.Id into grouping2 from m in grouping2.DefaultIfEmpty() select new { aname = a.Name, mname = m.Name }) .OrderBy(g => g.aname) - .GroupBy( - g => new { g.aname, g.mname }).FirstOrDefault() - .Select( - g => new { MyKey = g.aname, cnt = g.mname }) - .ToList(); + .GroupBy(g => new { g.aname, g.mname }) + .Select(g => new { MyKey = g.Key.aname, cnt = g.Key.mname }).FirstOrDefault(); + + Assert.Null(query); AssertSql( - ""); + @"SELECT TOP(1) [t2].[AnotherEntity11818_Name] AS [MyKey], [t5].[MaumarEntity11818_Name] AS [cnt] +FROM [Table] AS [t] +LEFT JOIN ( + SELECT [t0].[Id], [t0].[AnotherEntity11818_Name] + FROM [Table] AS [t0] + INNER JOIN [Table] AS [t1] ON [t0].[Id] = [t1].[Id] + WHERE [t0].[AnotherEntity11818_Name] IS NOT NULL +) AS [t2] ON [t].[Id] = [t2].[Id] +LEFT JOIN ( + SELECT [t3].[Id], [t3].[MaumarEntity11818_Name] + FROM [Table] AS [t3] + INNER JOIN [Table] AS [t4] ON [t3].[Id] = [t4].[Id] + WHERE [t3].[MaumarEntity11818_Name] IS NOT NULL +) AS [t5] ON [t].[Id] = [t5].[Id] +GROUP BY [t2].[AnotherEntity11818_Name], [t5].[MaumarEntity11818_Name]"); } } - private SqlServerTestStore CreateDatabase11818() - { - return CreateTestStore( - () => new MyContext11818(_options), - context => - { - context.SaveChanges(); - - ClearLog(); - }); - } - - private class MyContext11818 : DbContext + protected class MyContext11818 : DbContext { public MyContext11818(DbContextOptions options) : base(options) @@ -3279,37 +2933,40 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .WithOne() .HasForeignKey(b => b.Id); } - } - private class Entity11818 - { - public int Id { get; set; } - public string Name { get; set; } - } + public class Entity11818 + { + public int Id { get; set; } + public string Name { get; set; } + } - private class AnotherEntity11818 - { - public int Id { get; set; } - public string Name { get; set; } - } + public class AnotherEntity11818 + { + public int Id { get; set; } + public string Name { get; set; } + } - private class MaumarEntity11818 - { - public int Id { get; set; } - public string Name { get; set; } + public class MaumarEntity11818 + { + public int Id { get; set; } + public string Name { get; set; } + } } #endregion - #region Bug11803_11791 + #region Issue11803_11791 [ConditionalFact] - public virtual void Query_filter_with_db_set_should_not_block_other_filters() + public virtual async Task Query_filter_with_db_set_should_not_block_other_filters() { - using (CreateDatabase11803()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext11803(_options); - context.Factions.ToList(); + var query = context.Factions.ToList(); + + Assert.Empty(query); AssertSql( @"SELECT [f].[Id], [f].[Name] @@ -3321,13 +2978,16 @@ FROM [Leaders] AS [l] } } - [ConditionalFact(Skip = "Issue#18903")] - public virtual void Keyless_type_used_inside_defining_query() + [ConditionalFact] + public virtual async Task Keyless_type_used_inside_defining_query() { - using (CreateDatabase11803()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext11803(_options); - context.LeadersQuery.ToList(); + var query = context.LeadersQuery.ToList(); + + Assert.Single(query); AssertSql( @"SELECT [t].[Name] @@ -3340,33 +3000,7 @@ FROM [Leaders] AS [l] } } - private SqlServerTestStore CreateDatabase11803() - { - return CreateTestStore( - () => new MyContext11803(_options), - context => - { - var f1 = new Faction { Name = "Skeliege" }; - var f2 = new Faction { Name = "Monsters" }; - var f3 = new Faction { Name = "Nilfgaard" }; - var f4 = new Faction { Name = "Northern Realms" }; - var f5 = new Faction { Name = "Scioia'tael" }; - - var l11 = new Leader { Faction = f1, Name = "Bran Tuirseach" }; - var l12 = new Leader { Faction = f1, Name = "Crach an Craite" }; - var l13 = new Leader { Faction = f1, Name = "Eist Tuirseach" }; - var l14 = new Leader { Faction = f1, Name = "Harald the Cripple" }; - - context.Factions.AddRange(f1, f2, f3, f4, f5); - context.Leaders.AddRange(l11, l12, l13, l14); - - context.SaveChanges(); - - ClearLog(); - }); - } - - private class MyContext11803 : DbContext + protected class MyContext11803 : DbContext { public DbSet Factions { get; set; } public DbSet Leaders { get; set; } @@ -3382,63 +3016,70 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity().HasQueryFilter(l => l.Name.StartsWith("Bran")); // this one is ignored modelBuilder.Entity().HasQueryFilter(f => Leaders.Any(l => l.Name == "Crach an Craite")); -#pragma warning disable CS0618 // Type or member is obsolete - modelBuilder - .Entity() - .HasNoKey() - .ToQuery( - () => Set() - .Where(lq => lq.Name != "Foo") - .Select( - lq => new FactionQuery { Name = lq.Name })); modelBuilder .Entity() .HasNoKey() - .ToQuery( - () => Set() - .Where(fq => fq.Name != "Bar") - .Select( - fq => new LeaderQuery { Name = "Not Bar" })); -#pragma warning restore CS0618 // Type or member is obsolete - } - } - - private class Faction - { - public int Id { get; set; } - public string Name { get; set; } - - public List Leaders { get; set; } - } + .ToSqlQuery(@"SELECT [t].[Name] +FROM ( + SELECT [l].[Name] + FROM [Leaders] AS [l] + WHERE ([l].[Name] LIKE N'Bran' + N'%' AND (LEFT([l].[Name], LEN(N'Bran')) = N'Bran')) AND (([l].[Name] <> N'Foo') OR [l].[Name] IS NULL) +) AS [t] +WHERE ([t].[Name] <> N'Bar') OR [t].[Name] IS NULL"); + } - private class Leader - { - public int Id { get; set; } - public string Name { get; set; } - public Faction Faction { get; set; } - } + public void Seed() + { + var f1 = new Faction { Name = "Skeliege" }; + var f2 = new Faction { Name = "Monsters" }; + var f3 = new Faction { Name = "Nilfgaard" }; + var f4 = new Faction { Name = "Northern Realms" }; + var f5 = new Faction { Name = "Scioia'tael" }; - private class FactionQuery - { - public string Name { get; set; } - } + var l11 = new Leader { Faction = f1, Name = "Bran Tuirseach" }; + var l12 = new Leader { Faction = f1, Name = "Crach an Craite" }; + var l13 = new Leader { Faction = f1, Name = "Eist Tuirseach" }; + var l14 = new Leader { Faction = f1, Name = "Harald the Cripple" }; - private class LeaderQuery - { - public string Name { get; set; } + Factions.AddRange(f1, f2, f3, f4, f5); + Leaders.AddRange(l11, l12, l13, l14); + + SaveChanges(); + } + + public class Faction + { + public int Id { get; set; } + public string Name { get; set; } + + public List Leaders { get; set; } + } + + public class Leader + { + public int Id { get; set; } + public string Name { get; set; } + public Faction Faction { get; set; } + } + + public class LeaderQuery + { + public string Name { get; set; } + } } #endregion - #region Bug11923 + #region Issue11923 [ConditionalFact] - public virtual void Collection_without_setter_materialized_correctly() + public virtual async Task Collection_without_setter_materialized_correctly() { - using (CreateDatabase11923()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext11923(_options); var query1 = context.Blogs .Select( b => new @@ -3469,46 +3110,7 @@ public virtual void Collection_without_setter_materialized_correctly() } } - private SqlServerTestStore CreateDatabase11923() - { - return CreateTestStore( - () => new MyContext11923(_options), - context => - { - var p111 = new Post11923 { Name = "P111" }; - var p112 = new Post11923 { Name = "P112" }; - var p121 = new Post11923 { Name = "P121" }; - var p122 = new Post11923 { Name = "P122" }; - var p123 = new Post11923 { Name = "P123" }; - var p131 = new Post11923 { Name = "P131" }; - - var p211 = new Post11923 { Name = "P211" }; - var p212 = new Post11923 { Name = "P212" }; - var p221 = new Post11923 { Name = "P221" }; - var p222 = new Post11923 { Name = "P222" }; - var p223 = new Post11923 { Name = "P223" }; - var p231 = new Post11923 { Name = "P231" }; - - var b1 = new Blog11923 { Name = "B1" }; - var b2 = new Blog11923 { Name = "B2" }; - - b1.Posts1.AddRange(new[] { p111, p112 }); - b1.Posts2.AddRange(new[] { p121, p122, p123 }); - b1.Posts3.Add(p131); - - b2.Posts1.AddRange(new[] { p211, p212 }); - b2.Posts2.AddRange(new[] { p221, p222, p223 }); - b2.Posts3.Add(p231); - - context.Blogs.AddRange(b1, b2); - context.Posts.AddRange(p111, p112, p121, p122, p123, p131, p211, p212, p221, p222, p223, p231); - context.SaveChanges(); - - ClearLog(); - }); - } - - private class MyContext11923 : DbContext + protected class MyContext11923 : DbContext { public DbSet Blogs { get; set; } public DbSet Posts { get; set; } @@ -3531,59 +3133,92 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity(); } - } - private class Blog11923 - { - public Blog11923() + public void Seed() { - Posts1 = new List(); - Posts2 = new CustomCollection11923(); - Posts3 = new HashSet(); + var p111 = new Post11923 { Name = "P111" }; + var p112 = new Post11923 { Name = "P112" }; + var p121 = new Post11923 { Name = "P121" }; + var p122 = new Post11923 { Name = "P122" }; + var p123 = new Post11923 { Name = "P123" }; + var p131 = new Post11923 { Name = "P131" }; + + var p211 = new Post11923 { Name = "P211" }; + var p212 = new Post11923 { Name = "P212" }; + var p221 = new Post11923 { Name = "P221" }; + var p222 = new Post11923 { Name = "P222" }; + var p223 = new Post11923 { Name = "P223" }; + var p231 = new Post11923 { Name = "P231" }; + + var b1 = new Blog11923 { Name = "B1" }; + var b2 = new Blog11923 { Name = "B2" }; + + b1.Posts1.AddRange(new[] { p111, p112 }); + b1.Posts2.AddRange(new[] { p121, p122, p123 }); + b1.Posts3.Add(p131); + + b2.Posts1.AddRange(new[] { p211, p212 }); + b2.Posts2.AddRange(new[] { p221, p222, p223 }); + b2.Posts3.Add(p231); + + Blogs.AddRange(b1, b2); + Posts.AddRange(p111, p112, p121, p122, p123, p131, p211, p212, p221, p222, p223, p231); + SaveChanges(); } - public Blog11923(List posts1, CustomCollection11923 posts2, HashSet posts3) + public class Blog11923 { - Posts1 = posts1; - Posts2 = posts2; - Posts3 = posts3; - } + public Blog11923() + { + Posts1 = new List(); + Posts2 = new CustomCollection11923(); + Posts3 = new HashSet(); + } - public int Id { get; set; } - public string Name { get; set; } + public Blog11923(List posts1, CustomCollection11923 posts2, HashSet posts3) + { + Posts1 = posts1; + Posts2 = posts2; + Posts3 = posts3; + } - public List Posts1 { get; } - public CustomCollection11923 Posts2 { get; } - public HashSet Posts3 { get; } - } + public int Id { get; set; } + public string Name { get; set; } - private class Post11923 - { - public int Id { get; set; } - public string Name { get; set; } + public List Posts1 { get; } + public CustomCollection11923 Posts2 { get; } + public HashSet Posts3 { get; } + } - public List Comments { get; set; } - } + public class Post11923 + { + public int Id { get; set; } + public string Name { get; set; } - private class Comment11923 - { - public int Id { get; set; } - } + public List Comments { get; set; } + } - private class CustomCollection11923 : List - { + public class Comment11923 + { + public int Id { get; set; } + } + + public class CustomCollection11923 : List + { + } } #endregion - #region Bug11885 + #region Issue11885 [ConditionalFact] - public virtual void Average_with_cast() + public virtual async Task Average_with_cast() { - using (CreateDatabase11885()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext11885(_options); var prices = context.Prices.ToList(); ClearLog(); @@ -3636,59 +3271,7 @@ public virtual void Average_with_cast() } } - private SqlServerTestStore CreateDatabase11885() - { - return CreateTestStore( - () => new MyContext11885(_options), - context => - { - context.AddRange( - new Price11885 - { - IntColumn = 1, - NullableIntColumn = 1, - LongColumn = 1000, - NullableLongColumn = 1000, - FloatColumn = 0.1F, - NullableFloatColumn = 0.1F, - DoubleColumn = 0.000001, - NullableDoubleColumn = 0.000001, - DecimalColumn = 1.0m, - NullableDecimalColumn = 1.0m, - Price = 0.00112000m - }, - new Price11885 - { - IntColumn = 2, - NullableIntColumn = 2, - LongColumn = 2000, - NullableLongColumn = 2000, - FloatColumn = 0.2F, - NullableFloatColumn = 0.2F, - DoubleColumn = 0.000002, - NullableDoubleColumn = 0.000002, - DecimalColumn = 2.0m, - NullableDecimalColumn = 2.0m, - Price = 0.00232111m - }, - new Price11885 - { - IntColumn = 3, - LongColumn = 3000, - FloatColumn = 0.3F, - DoubleColumn = 0.000003, - DecimalColumn = 3.0m, - Price = 0.00345223m - } - ); - - context.SaveChanges(); - - ClearLog(); - }); - } - - private class MyContext11885 : DbContext + protected class MyContext11885 : DbContext { public DbSet Prices { get; set; } @@ -3707,54 +3290,95 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) b.Property(e => e.NullableDecimalColumn).HasColumnType("DECIMAL(18, 2)"); }); } - } - private class Price11885 - { - public int Id { get; set; } - public int IntColumn { get; set; } - public int? NullableIntColumn { get; set; } - public long LongColumn { get; set; } - public long? NullableLongColumn { get; set; } - public float FloatColumn { get; set; } - public float? NullableFloatColumn { get; set; } - public double DoubleColumn { get; set; } - public double? NullableDoubleColumn { get; set; } - public decimal DecimalColumn { get; set; } - public decimal? NullableDecimalColumn { get; set; } - public decimal Price { get; set; } + public void Seed() + { + AddRange( + new Price11885 + { + IntColumn = 1, + NullableIntColumn = 1, + LongColumn = 1000, + NullableLongColumn = 1000, + FloatColumn = 0.1F, + NullableFloatColumn = 0.1F, + DoubleColumn = 0.000001, + NullableDoubleColumn = 0.000001, + DecimalColumn = 1.0m, + NullableDecimalColumn = 1.0m, + Price = 0.00112000m + }, + new Price11885 + { + IntColumn = 2, + NullableIntColumn = 2, + LongColumn = 2000, + NullableLongColumn = 2000, + FloatColumn = 0.2F, + NullableFloatColumn = 0.2F, + DoubleColumn = 0.000002, + NullableDoubleColumn = 0.000002, + DecimalColumn = 2.0m, + NullableDecimalColumn = 2.0m, + Price = 0.00232111m + }, + new Price11885 + { + IntColumn = 3, + LongColumn = 3000, + FloatColumn = 0.3F, + DoubleColumn = 0.000003, + DecimalColumn = 3.0m, + Price = 0.00345223m + } + ); + + SaveChanges(); + } + + public class Price11885 + { + public int Id { get; set; } + public int IntColumn { get; set; } + public int? NullableIntColumn { get; set; } + public long LongColumn { get; set; } + public long? NullableLongColumn { get; set; } + public float FloatColumn { get; set; } + public float? NullableFloatColumn { get; set; } + public double DoubleColumn { get; set; } + public double? NullableDoubleColumn { get; set; } + public decimal DecimalColumn { get; set; } + public decimal? NullableDecimalColumn { get; set; } + public decimal Price { get; set; } + } } #endregion - #region Bug12582 + #region Issue12582 [ConditionalFact] - public virtual void Include_collection_with_OfType_base() + public virtual async Task Include_collection_with_OfType_base() { - using (CreateDatabase12582()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext12582(_options); var query = context.Employees .Include(i => i.Devices) - .OfType() + .OfType() .ToList(); Assert.Single(query); - var employee = (Employee12582)query[0]; + var employee = (MyContext12582.Employee12582)query[0]; Assert.Equal(2, employee.Devices.Count); } - } - [ConditionalFact] - public virtual void Correlated_collection_with_OfType_base() - { - using (CreateDatabase12582()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext12582(_options); var query = context.Employees - .Select(e => e.Devices.Where(d => d.Device != "foo").Cast()) + .Select(e => e.Devices.Where(d => d.Device != "foo").Cast()) .ToList(); Assert.Single(query); @@ -3763,70 +3387,64 @@ public virtual void Correlated_collection_with_OfType_base() } } - private SqlServerTestStore CreateDatabase12582() + private class MyContext12582 : DbContext { - return CreateTestStore( - () => new MyContext12582(_options), - context => - { - var d1 = new EmployeeDevice12582 { Device = "d1" }; - var d2 = new EmployeeDevice12582 { Device = "d2" }; - var e = new Employee12582 { Devices = new List { d1, d2 }, Name = "e" }; - - context.Devices.AddRange(d1, d2); - context.Employees.Add(e); - context.SaveChanges(); + public DbSet Employees { get; set; } + public DbSet Devices { get; set; } - ClearLog(); - }); - } + public MyContext12582(DbContextOptions options) + : base(options) + { + } - private interface IEmployee12582 - { - string Name { get; set; } - } + public void Seed() + { + var d1 = new EmployeeDevice12582 { Device = "d1" }; + var d2 = new EmployeeDevice12582 { Device = "d2" }; + var e = new Employee12582 { Devices = new List { d1, d2 }, Name = "e" }; - private class Employee12582 : IEmployee12582 - { - public int Id { get; set; } - public string Name { get; set; } - public ICollection Devices { get; set; } - } + Devices.AddRange(d1, d2); + Employees.Add(e); + SaveChanges(); + } - private interface IEmployeeDevice12582 - { - string Device { get; set; } - } + public interface IEmployee12582 + { + string Name { get; set; } + } - private class EmployeeDevice12582 : IEmployeeDevice12582 - { - public int Id { get; set; } - public int EmployeeId { get; set; } - public string Device { get; set; } - public Employee12582 Employee { get; set; } - } + public class Employee12582 : IEmployee12582 + { + public int Id { get; set; } + public string Name { get; set; } + public ICollection Devices { get; set; } + } - private class MyContext12582 : DbContext - { - public DbSet Employees { get; set; } - public DbSet Devices { get; set; } + public interface IEmployeeDevice12582 + { + string Device { get; set; } + } - public MyContext12582(DbContextOptions options) - : base(options) + public class EmployeeDevice12582 : IEmployeeDevice12582 { + public int Id { get; set; } + public int EmployeeId { get; set; } + public string Device { get; set; } + public Employee12582 Employee { get; set; } } } #endregion - #region Bug12748 + #region Issue12748 [ConditionalFact] - public virtual void Correlated_collection_correctly_associates_entities_with_byte_array_keys() + public virtual async Task Correlated_collection_correctly_associates_entities_with_byte_array_keys() { - using (CreateDatabase12748()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext12748(_options); var query = from blog in context.Blogs select new { @@ -3839,20 +3457,7 @@ public virtual void Correlated_collection_correctly_associates_entities_with_byt } } - private SqlServerTestStore CreateDatabase12748() - { - return CreateTestStore( - () => new MyContext12748(_options), - context => - { - context.Blogs.Add(new Blog12748 { Name = Encoding.UTF8.GetBytes("Awesome Blog") }); - context.Comments.Add(new Comment12748 { BlogName = Encoding.UTF8.GetBytes("Awesome Blog") }); - context.SaveChanges(); - ClearLog(); - }); - } - - private class MyContext12748 : DbContext + protected class MyContext12748 : DbContext { public DbSet Blogs { get; set; } public DbSet Comments { get; set; } @@ -3865,66 +3470,50 @@ public MyContext12748(DbContextOptions options) protected override void OnModelCreating(ModelBuilder modelBuilder) { } - } - private class Blog12748 - { - [Key] - public byte[] Name { get; set; } + public void Seed() + { + Blogs.Add(new Blog12748 { Name = Encoding.UTF8.GetBytes("Awesome Blog") }); + Comments.Add(new Comment12748 { BlogName = Encoding.UTF8.GetBytes("Awesome Blog") }); + SaveChanges(); + } - public List Comments { get; set; } - } + public class Blog12748 + { + [Key] + public byte[] Name { get; set; } - private class Comment12748 - { - public int Id { get; set; } - public byte[] BlogName { get; set; } - public Blog12748 Blog { get; set; } + public List Comments { get; set; } + } + + public class Comment12748 + { + public int Id { get; set; } + public byte[] BlogName { get; set; } + public Blog12748 Blog { get; set; } + } } #endregion - #region Bug13025 + #region Issue13025 [ConditionalFact] - public virtual void Find_underlying_property_after_GroupJoin_DefaultIfEmpty() + public virtual async Task Find_underlying_property_after_GroupJoin_DefaultIfEmpty() { - using (CreateDatabase13025()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext13025(_options); var query = (from e in context.Employees join d in context.EmployeeDevices on e.Id equals d.EmployeeId into grouping from j in grouping.DefaultIfEmpty() - select new Holder13025 { Name = e.Name, DeviceId = j.DeviceId }).ToList(); + select new MyContext13025.Holder13025 { Name = e.Name, DeviceId = j.DeviceId }).ToList(); } } - private class Holder13025 - { - public string Name { get; set; } - public int? DeviceId { get; set; } - } - - private SqlServerTestStore CreateDatabase13025() - { - return CreateTestStore( - () => new MyContext13025(_options), - context => - { - context.AddRange( - new Employee13025 - { - Name = "Test1", - Devices = new List { new EmployeeDevice13025 { DeviceId = 1, Device = "Battery" } } - }); - - context.SaveChanges(); - ClearLog(); - }); - } - - private class MyContext13025 : DbContext + protected class MyContext13025 : DbContext { public DbSet Employees { get; set; } public DbSet EmployeeDevices { get; set; } @@ -3937,50 +3526,60 @@ public MyContext13025(DbContextOptions options) protected override void OnModelCreating(ModelBuilder modelBuilder) { } - } - private class Employee13025 - { - public int Id { get; set; } - public string Name { get; set; } - public ICollection Devices { get; set; } - } + public void Seed() + { + AddRange( + new Employee13025 + { + Name = "Test1", + Devices = new List { new EmployeeDevice13025 { DeviceId = 1, Device = "Battery" } } + }); - private class EmployeeDevice13025 - { - public int Id { get; set; } - public short DeviceId { get; set; } - public int EmployeeId { get; set; } - public string Device { get; set; } - public Employee13025 Employee { get; set; } + SaveChanges(); + } + + public class Holder13025 + { + public string Name { get; set; } + public int? DeviceId { get; set; } + } + + public class Employee13025 + { + public int Id { get; set; } + public string Name { get; set; } + public ICollection Devices { get; set; } + } + + public class EmployeeDevice13025 + { + public int Id { get; set; } + public short DeviceId { get; set; } + public int EmployeeId { get; set; } + public string Device { get; set; } + public Employee13025 Employee { get; set; } + } } #endregion - #region Bug12170 + #region Issue12170 [ConditionalFact] - public virtual void Weak_entities_with_query_filter_subquery_flattening() + public virtual async Task Weak_entities_with_query_filter_subquery_flattening() { - using (CreateDatabase12170()) + var contextFactory = await InitializeAsync(); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext12170(_options); var result = context.Definitions.Any(); - } - } - private SqlServerTestStore CreateDatabase12170() - { - return CreateTestStore( - () => new MyContext12170(_options), - context => - { - context.SaveChanges(); - ClearLog(); - }); + Assert.False(result); + } } - private class MyContext12170 : DbContext + protected class MyContext12170 : DbContext { public virtual DbSet Definitions { get; set; } public virtual DbSet DefinitionHistories { get; set; } @@ -3998,63 +3597,59 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity().OwnsOne(h => h.EndedPoint); } - } - [Owned] - private class OptionalChangePoint12170 - { - public DateTime? Timestamp { get; set; } - } + [Owned] + public class OptionalChangePoint12170 + { + public DateTime? Timestamp { get; set; } + } - [Owned] - private class MasterChangeInfo12170 - { - public virtual OptionalChangePoint12170 RemovedPoint { get; set; } - } + [Owned] + public class MasterChangeInfo12170 + { + public virtual OptionalChangePoint12170 RemovedPoint { get; set; } + } - private class DefinitionHistory12170 - { - public int Id { get; set; } - public int MacGuffinDefinitionID { get; set; } - public virtual Definition12170 Definition { get; set; } - public OptionalChangePoint12170 EndedPoint { get; set; } - } + public class DefinitionHistory12170 + { + public int Id { get; set; } + public int MacGuffinDefinitionID { get; set; } + public virtual Definition12170 Definition { get; set; } + public OptionalChangePoint12170 EndedPoint { get; set; } + } - private class Definition12170 - { - public int Id { get; set; } - public virtual MasterChangeInfo12170 ChangeInfo { get; set; } + public class Definition12170 + { + public int Id { get; set; } + public virtual MasterChangeInfo12170 ChangeInfo { get; set; } - public virtual ICollection HistoryEntries { get; set; } - public virtual DefinitionHistory12170 LatestHistoryEntry { get; set; } - public int? LatestHistoryEntryID { get; set; } + public virtual ICollection HistoryEntries { get; set; } + public virtual DefinitionHistory12170 LatestHistoryEntry { get; set; } + public int? LatestHistoryEntryID { get; set; } + } } #endregion - #region Bug11944 + #region Issue11944 [ConditionalFact] - public virtual void Include_collection_works_when_defined_on_intermediate_type() + public virtual async Task Include_collection_works_when_defined_on_intermediate_type() { - using (CreateDatabase11944()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext11944(_options); - var query = context.Schools.Include(s => ((ElementarySchool11944)s).Students); + var query = context.Schools.Include(s => ((MyContext11944.ElementarySchool11944)s).Students); var result = query.ToList(); Assert.Equal(2, result.Count); - Assert.Equal(2, result.OfType().Single().Students.Count); + Assert.Equal(2, result.OfType().Single().Students.Count); } - } - [ConditionalFact] - public virtual void Correlated_collection_works_when_defined_on_intermediate_type() - { - using (CreateDatabase11944()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext11944(_options); - var query = context.Schools.Select(s => ((ElementarySchool11944)s).Students.Where(ss => true).ToList()); + var query = context.Schools.Select(s => ((MyContext11944.ElementarySchool11944)s).Students.Where(ss => true).ToList()); var result = query.ToList(); Assert.Equal(2, result.Count); @@ -4062,27 +3657,7 @@ public virtual void Correlated_collection_works_when_defined_on_intermediate_typ } } - private SqlServerTestStore CreateDatabase11944() - { - return CreateTestStore( - () => new MyContext11944(_options), - context => - { - var student1 = new Student11944(); - var student2 = new Student11944(); - var school = new School11944(); - var elementarySchool = new ElementarySchool11944 { Students = new List { student1, student2 } }; - - context.Students.AddRange(student1, student2); - context.Schools.AddRange(school); - context.ElementarySchools.Add(elementarySchool); - - context.SaveChanges(); - ClearLog(); - }); - } - - private class MyContext11944 : DbContext + protected class MyContext11944 : DbContext { public DbSet Students { get; set; } public DbSet Schools { get; set; } @@ -4097,38 +3672,53 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity().HasMany(s => s.Students).WithOne(s => s.School); } - } - private class Student11944 - { - public int Id { get; set; } - public ElementarySchool11944 School { get; set; } - } + public void Seed() + { + var student1 = new Student11944(); + var student2 = new Student11944(); + var school = new School11944(); + var elementarySchool = new ElementarySchool11944 { Students = new List { student1, student2 } }; - private class School11944 - { - public int Id { get; set; } - } + Students.AddRange(student1, student2); + Schools.AddRange(school); + ElementarySchools.Add(elementarySchool); - private abstract class PrimarySchool11944 : School11944 - { - public List Students { get; set; } - } + SaveChanges(); + } - private class ElementarySchool11944 : PrimarySchool11944 - { + public class Student11944 + { + public int Id { get; set; } + public ElementarySchool11944 School { get; set; } + } + + public class School11944 + { + public int Id { get; set; } + } + + public abstract class PrimarySchool11944 : School11944 + { + public List Students { get; set; } + } + + public class ElementarySchool11944 : PrimarySchool11944 + { + } } #endregion - #region Bug13118 + #region Issue13118 [ConditionalFact] - public virtual void DateTime_Contains_with_smalldatetime_generates_correct_literal() + public virtual async Task DateTime_Contains_with_smalldatetime_generates_correct_literal() { - using (CreateDatabase13118()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext13118(_options); var testDateList = new List { new DateTime(2018, 10, 07) }; var findRecordsWithDateInList = context.ReproEntity .Where(a => testDateList.Contains(a.MyTime)) @@ -4143,21 +3733,6 @@ FROM [ReproEntity] AS [r] } } - private SqlServerTestStore CreateDatabase13118() - { - return CreateTestStore( - () => new MyContext13118(_options), - context => - { - context.AddRange( - new ReproEntity13118 { MyTime = new DateTime(2018, 10, 07) }, - new ReproEntity13118 { MyTime = new DateTime(2018, 10, 08) }); - - context.SaveChanges(); - ClearLog(); - }); - } - private class MyContext13118 : DbContext { public virtual DbSet ReproEntity { get; set; } @@ -4171,9 +3746,18 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity(e => e.Property("MyTime").HasColumnType("smalldatetime")); } - } - private class ReproEntity13118 + public void Seed() + { + AddRange( + new ReproEntity13118 { MyTime = new DateTime(2018, 10, 07) }, + new ReproEntity13118 { MyTime = new DateTime(2018, 10, 08) }); + + SaveChanges(); + } + } + + private class ReproEntity13118 { public Guid Id { get; set; } public DateTime MyTime { get; set; } @@ -4181,17 +3765,18 @@ private class ReproEntity13118 #endregion - #region Bug12732 + #region Issue12732 [ConditionalFact] - public virtual void Nested_contains_with_enum() + public virtual async Task Nested_contains_with_enum() { - using (CreateDatabase12732()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext12732(_options); var key = Guid.Parse("5f221fb9-66f4-442a-92c9-d97ed5989cc7"); var keys = new List { Guid.Parse("0a47bcb7-a1cb-4345-8944-c58f82d6aac7"), key }; - var todoTypes = new List { TodoType.foo0 }; + var todoTypes = new List { MyContext12732.TodoType.foo0 }; var query = context.Todos .Where(x => keys.Contains(todoTypes.Contains(x.Type) ? key : key)) @@ -4211,20 +3796,7 @@ ELSE @__key_2 } } - private SqlServerTestStore CreateDatabase12732() - { - return CreateTestStore( - () => new MyContext12732(_options), - context => - { - context.Add( - new Todo { Type = TodoType.foo0 }); - context.SaveChanges(); - ClearLog(); - }); - } - - private class MyContext12732 : DbContext + protected class MyContext12732 : DbContext { public DbSet Todos { get; set; } @@ -4232,29 +3804,36 @@ public MyContext12732(DbContextOptions options) : base(options) { } - } - private class Todo - { - public Guid Id { get; set; } - public TodoType Type { get; set; } - } + public void Seed() + { + Add(new Todo { Type = TodoType.foo0 }); + SaveChanges(); + } - private enum TodoType - { - foo0 = 0 + public class Todo + { + public Guid Id { get; set; } + public TodoType Type { get; set; } + } + + public enum TodoType + { + foo0 = 0 + } } #endregion - #region Bug13157 + #region Issue13157 [ConditionalFact] - public virtual void Correlated_subquery_with_owned_navigation_being_compared_to_null_works() + public virtual async Task Correlated_subquery_with_owned_navigation_being_compared_to_null_works() { - using (CreateDatabase13157()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext13157(_options); var partners = context.Partners .Select( x => new @@ -4292,29 +3871,7 @@ FROM [Partners] AS [p] } } - private SqlServerTestStore CreateDatabase13157() - { - return CreateTestStore( - () => new MyContext13157(_options), - context => - { - context.AddRange( - new Partner13157 - { - Addresses = new List - { - new Address13157 { Turnovers = new AddressTurnovers13157 { AmountIn = 10 } }, - new Address13157 { Turnovers = null }, - } - } - ); - - context.SaveChanges(); - ClearLog(); - }); - } - - private class MyContext13157 : DbContext + protected class MyContext13157 : DbContext { public virtual DbSet Partners { get; set; } @@ -4327,63 +3884,61 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity().OwnsOne(x => x.Turnovers); } - } - private class Partner13157 - { - public int Id { get; set; } - public ICollection Addresses { get; set; } - } + public void Seed() + { + AddRange( + new Partner13157 + { + Addresses = new List + { + new Address13157 { Turnovers = new AddressTurnovers13157 { AmountIn = 10 } }, + new Address13157 { Turnovers = null }, + } + } + ); - private class Address13157 - { - public int Id { get; set; } - public AddressTurnovers13157 Turnovers { get; set; } - } + SaveChanges(); + } - private class AddressTurnovers13157 - { - public int AmountIn { get; set; } + public class Partner13157 + { + public int Id { get; set; } + public ICollection Addresses { get; set; } + } + + public class Address13157 + { + public int Id { get; set; } + public AddressTurnovers13157 Turnovers { get; set; } + } + + public class AddressTurnovers13157 + { + public int AmountIn { get; set; } + } } #endregion - #region Bug13346 + #region Issue13346 [ConditionalFact] - public virtual void ToQuery_can_define_in_own_terms_using_FromSql() + public virtual async Task ToQuery_can_define_in_own_terms_using_FromSql() { - using (CreateDatabase13346()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext13346(_options); - var query = context.Set().ToList(); + var query = context.Set().ToList(); Assert.Equal(4, query.Count); - AssertSql( - "SELECT o.Amount From Orders AS o"); + AssertSql("SELECT o.Amount From Orders AS o"); } } - private SqlServerTestStore CreateDatabase13346() - { - return CreateTestStore( - () => new MyContext13346(_options), - context => - { - context.AddRange( - new Order13346 { Amount = 1 }, - new Order13346 { Amount = 2 }, - new Order13346 { Amount = 3 }, - new Order13346 { Amount = 4 } - ); - - context.SaveChanges(); - ClearLog(); - }); - } - - private class MyContext13346 : DbContext + protected class MyContext13346 : DbContext { public virtual DbSet Orders { get; set; } @@ -4398,30 +3953,43 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasNoKey() .ToSqlQuery("SELECT o.Amount From Orders AS o"); } - } - private class Order13346 - { - public int Id { get; set; } - public int Amount { get; set; } - } + public void Seed() + { + AddRange( + new Order13346 { Amount = 1 }, + new Order13346 { Amount = 2 }, + new Order13346 { Amount = 3 }, + new Order13346 { Amount = 4 } + ); - private class OrderSummary13346 - { - public int Amount { get; set; } + SaveChanges(); + } + + public class Order13346 + { + public int Id { get; set; } + public int Amount { get; set; } + } + + public class OrderSummary13346 + { + public int Amount { get; set; } + } } #endregion - #region Bug13079 + #region Issue13079 [ConditionalFact] - public virtual void Multilevel_owned_entities_determine_correct_nullability() + public virtual async Task Multilevel_owned_entities_determine_correct_nullability() { - using (CreateDatabase13079()) + var contextFactory = await InitializeAsync(); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext13079(_options); - context.Add(new BaseEntity13079()); + context.Add(new MyContext13079.BaseEntity13079()); context.SaveChanges(); AssertSql( @@ -4436,14 +4004,7 @@ FROM [BaseEntities] } } - private SqlServerTestStore CreateDatabase13079() - { - return CreateTestStore( - () => new MyContext13079(_options), - context => ClearLog()); - } - - private class MyContext13079 : DbContext + protected class MyContext13079 : DbContext { public virtual DbSet BaseEntities { get; set; } @@ -4456,40 +4017,41 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity().OwnsOne(e => e.Data, b => b.OwnsOne(e => e.SubData)); } - } - private class BaseEntity13079 - { - public int Id { get; set; } - } + public class BaseEntity13079 + { + public int Id { get; set; } + } - private class DerivedEntity13079 : BaseEntity13079 - { - public int Property { get; set; } - public OwnedData13079 Data { get; set; } - } + public class DerivedEntity13079 : BaseEntity13079 + { + public int Property { get; set; } + public OwnedData13079 Data { get; set; } + } - private class OwnedData13079 - { - public int Property { get; set; } - public OwnedSubData13079 SubData { get; set; } - } + public class OwnedData13079 + { + public int Property { get; set; } + public OwnedSubData13079 SubData { get; set; } + } - private class OwnedSubData13079 - { - public int Property { get; set; } + public class OwnedSubData13079 + { + public int Property { get; set; } + } } #endregion - #region Bug13587 + #region Issue13587 [ConditionalFact] - public virtual void Type_casting_inside_sum() + public virtual async Task Type_casting_inside_sum() { - using (CreateDatabase13587()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext13587(_options); var result = context.InventoryPools.Sum(p => (decimal)p.Quantity); AssertSql( @@ -4498,22 +4060,7 @@ public virtual void Type_casting_inside_sum() } } - private SqlServerTestStore CreateDatabase13587() - { - return CreateTestStore( - () => new MyContext13587(_options), - context => - { - context.InventoryPools.Add( - new InventoryPool13587 { Quantity = 2 }); - - context.SaveChanges(); - - ClearLog(); - }); - } - - private class MyContext13587 : DbContext + protected class MyContext13587 : DbContext { public virtual DbSet InventoryPools { get; set; } @@ -4521,24 +4068,32 @@ public MyContext13587(DbContextOptions options) : base(options) { } - } - private class InventoryPool13587 - { - public int Id { get; set; } - public double Quantity { get; set; } + public void Seed() + { + InventoryPools.Add(new InventoryPool13587 { Quantity = 2 }); + + SaveChanges(); + } + + public class InventoryPool13587 + { + public int Id { get; set; } + public double Quantity { get; set; } + } } #endregion - #region Bug12518 + #region Issue12518 [ConditionalFact] - public virtual void Projecting_entity_with_value_converter_and_include_works() + public virtual async Task Projecting_entity_with_value_converter_and_include_works() { - using (CreateDatabase12518()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext12518(_options); var result = context.Parents.Include(p => p.Child).OrderBy(e => e.Id).FirstOrDefault(); AssertSql( @@ -4550,11 +4105,12 @@ FROM [Parents] AS [p] } [ConditionalFact(Skip = "Issue #22256")] - public virtual void Projecting_column_with_value_converter_of_ulong_byte_array() + public virtual async Task Projecting_column_with_value_converter_of_ulong_byte_array() { - using (CreateDatabase12518()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext12518(_options); var result = context.Parents.OrderBy(e => e.Id).Select(p => (ulong?)p.Child.ULongRowVersion).FirstOrDefault(); AssertSql( @@ -4565,20 +4121,7 @@ FROM [Parents] AS [p] } } - private SqlServerTestStore CreateDatabase12518() - { - return CreateTestStore( - () => new MyContext12518(_options), - context => - { - context.Parents.Add(new Parent12518()); - context.SaveChanges(); - - ClearLog(); - }); - } - - private class MyContext12518 : DbContext + protected class MyContext12518 : DbContext { public virtual DbSet Parents { get; set; } public virtual DbSet Children { get; set; } @@ -4602,54 +4145,62 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity(); } - } - private class Parent12518 - { - public Guid Id { get; set; } = Guid.NewGuid(); - public Guid? ChildId { get; set; } - public Child12518 Child { get; set; } - } + public void Seed() + { + Parents.Add(new Parent12518()); + SaveChanges(); + } - private class Child12518 - { - public Guid Id { get; set; } = Guid.NewGuid(); - public ulong ULongRowVersion { get; set; } - public Guid ParentId { get; set; } - public Parent12518 Parent { get; set; } + public class Parent12518 + { + public Guid Id { get; set; } = Guid.NewGuid(); + public Guid? ChildId { get; set; } + public Child12518 Child { get; set; } + } + + public class Child12518 + { + public Guid Id { get; set; } = Guid.NewGuid(); + public ulong ULongRowVersion { get; set; } + public Guid ParentId { get; set; } + public Parent12518 Parent { get; set; } + } } #endregion - #region Bug12549 + #region Issue12549 [ConditionalFact] - public virtual void Union_and_insert_12549() + public virtual async Task Union_and_insert_12549() { - using (CreateDatabase12549()) + var contextFactory = await InitializeAsync(); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext12549(_options); var id1 = 1; var id2 = 2; - var ids1 = context.Set() + var ids1 = context.Set() .Where(x => x.Id == id1) .Select(x => x.Id); - var ids2 = context.Set() + var ids2 = context.Set() .Where(x => x.Id == id2) .Select(x => x.Id); var results = ids1.Union(ids2).ToList(); - context.AddRange(new Table1_12549(), new Table2_12549(), new Table1_12549(), new Table2_12549()); + context.AddRange( + new MyContext12549.Table1_12549(), + new MyContext12549.Table2_12549(), + new MyContext12549.Table1_12549(), + new MyContext12549.Table2_12549()); context.SaveChanges(); } } - private SqlServerTestStore CreateDatabase12549() - => CreateTestStore(() => new MyContext12549(_options), context => { }); - private class MyContext12549 : DbContext { public DbSet Table1 { get; set; } @@ -4659,55 +4210,52 @@ public MyContext12549(DbContextOptions options) : base(options) { } - } - private class Table1_12549 - { - public int Id { get; set; } - } + public class Table1_12549 + { + public int Id { get; set; } + } - private class Table2_12549 - { - public int Id { get; set; } + public class Table2_12549 + { + public int Id { get; set; } + } } #endregion - #region Bug16233 + #region Issue16233 [ConditionalFact] - public virtual void Derived_reference_is_skipped_when_base_type() + public virtual async Task Derived_reference_is_skipped_when_base_type() { - using (CreateDatabase16233()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext16233(_options); - var result = context.Bases.Include(p => ((DerivedType16233)p).Reference).OrderBy(b => b.Id).ToList(); + var result = context.Bases.Include(p => ((MyContext16233.DerivedType16233)p).Reference).OrderBy(b => b.Id).ToList(); Assert.Equal(3, result.Count); - Assert.NotNull(Assert.IsType(result[1]).Reference); - Assert.Null(Assert.IsType(result[2]).Reference); - Assert.True(context.Entry(Assert.IsType(result[2])).Reference("Reference").IsLoaded); + Assert.NotNull(Assert.IsType(result[1]).Reference); + Assert.Null(Assert.IsType(result[2]).Reference); + Assert.True(context.Entry(Assert.IsType(result[2])).Reference("Reference").IsLoaded); AssertSql( @"SELECT [b].[Id], [b].[Discriminator], [r].[Id], [r].[DerivedTypeId] FROM [Bases] AS [b] LEFT JOIN [Reference16233] AS [r] ON [b].[Id] = [r].[DerivedTypeId] ORDER BY [b].[Id]"); + ClearLog(); } - } - [ConditionalFact] - public virtual void Derived_reference_is_skipped_when_base_type_no_tracking() - { - using (CreateDatabase16233()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext16233(_options); - var result = context.Bases.AsNoTracking().Include(p => ((DerivedType16233)p).Reference).OrderBy(b => b.Id).ToList(); + var result = context.Bases.AsNoTracking().Include(p => ((MyContext16233.DerivedType16233)p).Reference).OrderBy(b => b.Id).ToList(); Assert.Equal(3, result.Count); - Assert.NotNull(Assert.IsType(result[1]).Reference); - Assert.NotNull(Assert.IsType(result[1]).Reference.DerivedType); - Assert.Null(Assert.IsType(result[2]).Reference); + Assert.NotNull(Assert.IsType(result[1]).Reference); + Assert.NotNull(Assert.IsType(result[1]).Reference.DerivedType); + Assert.Null(Assert.IsType(result[2]).Reference); AssertSql( @"SELECT [b].[Id], [b].[Discriminator], [r].[Id], [r].[DerivedTypeId] @@ -4717,23 +4265,6 @@ FROM [Bases] AS [b] } } - private SqlServerTestStore CreateDatabase16233() - { - return CreateTestStore( - () => new MyContext16233(_options), - context => - { - context.AddRange( - new BaseType16233(), - new DerivedType16233 { Reference = new Reference16233() }, - new DerivedType16233()); - - context.SaveChanges(); - - ClearLog(); - }); - } - private class MyContext16233 : DbContext { public virtual DbSet Bases { get; set; } @@ -4743,47 +4274,59 @@ public MyContext16233(DbContextOptions options) : base(options) { } - } - private class BaseType16233 - { - public int Id { get; set; } - } + public void Seed() + { + AddRange( + new BaseType16233(), + new DerivedType16233 { Reference = new Reference16233() }, + new DerivedType16233()); - private class DerivedType16233 : BaseType16233 - { - public Reference16233 Reference { get; set; } - } + SaveChanges(); + } - private class Reference16233 - { - public int Id { get; set; } - public int DerivedTypeId { get; set; } - public DerivedType16233 DerivedType { get; set; } + public class BaseType16233 + { + public int Id { get; set; } + } + + public class DerivedType16233 : BaseType16233 + { + public Reference16233 Reference { get; set; } + } + + public class Reference16233 + { + public int Id { get; set; } + public int DerivedTypeId { get; set; } + public DerivedType16233 DerivedType { get; set; } + } } #endregion - #region Bug15684 + #region Issue15684 [ConditionalFact] - public virtual void Projection_failing_with_EnumToStringConverter() + public virtual async Task Projection_failing_with_EnumToStringConverter() { - using (CreateDatabase15684()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext15684(_options); var query = from p in context.Products join c in context.Categories on p.CategoryId equals c.Id into grouping from c in grouping.DefaultIfEmpty() - select new ProductDto15684 + select new MyContext15684.ProductDto15684 { Id = p.Id, Name = p.Name, CategoryName = c == null ? "Other" : c.Name, - CategoryStatus = c == null ? CategoryStatus15684.Active : c.Status + CategoryStatus = c == null ? MyContext15684.CategoryStatus15684.Active : c.Status }; var result = query.ToList(); Assert.Equal(2, result.Count); + AssertSql( @"SELECT [p].[Id], [p].[Name], CASE WHEN [c].[Id] IS NULL THEN N'Other' @@ -4797,26 +4340,7 @@ FROM [Products] AS [p] } } - private SqlServerTestStore CreateDatabase15684() - => CreateTestStore( - () => new MyContext15684(_options), - context => - { - context.Products.Add( - new Product15684 - { - Name = "Apple", - Category = new Category15684 { Name = "Fruit", Status = CategoryStatus15684.Active } - }); - - context.Products.Add(new Product15684 { Name = "Bike" }); - - context.SaveChanges(); - - ClearLog(); - }); - - private class MyContext15684 : DbContext + protected class MyContext15684 : DbContext { public DbSet Categories { get; set; } public DbSet Products { get; set; } @@ -4833,49 +4357,63 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .Property(e => e.Status) .HasConversion(new EnumToStringConverter()); } - } - private class Product15684 - { - [Key] - public int Id { get; set; } + public void Seed() + { + Products.Add( + new Product15684 + { + Name = "Apple", + Category = new Category15684 { Name = "Fruit", Status = CategoryStatus15684.Active } + }); - [Required] - public string Name { get; set; } + Products.Add(new Product15684 { Name = "Bike" }); - public int? CategoryId { get; set; } + SaveChanges(); + } - public Category15684 Category { get; set; } - } + public class Product15684 + { + [Key] + public int Id { get; set; } - private class Category15684 - { - [Key] - public int Id { get; set; } + [Required] + public string Name { get; set; } - [Required] - public string Name { get; set; } + public int? CategoryId { get; set; } - public CategoryStatus15684 Status { get; set; } - } + public Category15684 Category { get; set; } + } - private class ProductDto15684 - { - public string CategoryName { get; set; } - public CategoryStatus15684 CategoryStatus { get; set; } - public int Id { get; set; } - public string Name { get; set; } - } + public class Category15684 + { + [Key] + public int Id { get; set; } - private enum CategoryStatus15684 - { - Active = 0, - Removed = 1 + [Required] + public string Name { get; set; } + + public CategoryStatus15684 Status { get; set; } + } + + public class ProductDto15684 + { + public string CategoryName { get; set; } + public CategoryStatus15684 CategoryStatus { get; set; } + public int Id { get; set; } + public string Name { get; set; } + } + + public enum CategoryStatus15684 + { + Active = 0, + Removed = 1 + } } #endregion - #region Bug15204 + #region Issue15204 private MemberInfo GetMemberInfo(Type type, string name) { @@ -4883,33 +4421,34 @@ private MemberInfo GetMemberInfo(Type type, string name) } [ConditionalFact] - public virtual void Null_check_removal_applied_recursively() + public virtual async Task Null_check_removal_applied_recursively() { - using (CreateDatabase15204()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - var userParam = Expression.Parameter(typeof(TBuilding15204), "s"); - var builderProperty = Expression.MakeMemberAccess(userParam, GetMemberInfo(typeof(TBuilding15204), "Builder")); - var cityProperty = Expression.MakeMemberAccess(builderProperty, GetMemberInfo(typeof(TBuilder15204), "City")); - var nameProperty = Expression.MakeMemberAccess(cityProperty, GetMemberInfo(typeof(TCity15204), "Name")); + var userParam = Expression.Parameter(typeof(MyContext15204.TBuilding15204), "s"); + var builderProperty = Expression.MakeMemberAccess(userParam, GetMemberInfo(typeof(MyContext15204.TBuilding15204), "Builder")); + var cityProperty = Expression.MakeMemberAccess(builderProperty, GetMemberInfo(typeof(MyContext15204.TBuilder15204), "City")); + var nameProperty = Expression.MakeMemberAccess(cityProperty, GetMemberInfo(typeof(MyContext15204.TCity15204), "Name")); //{s => (IIF((IIF((s.Builder == null), null, s.Builder.City) == null), null, s.Builder.City.Name) == "Leeds")} - var selection = Expression.Lambda>( + var selection = Expression.Lambda>( Expression.Equal( Expression.Condition( Expression.Equal( Expression.Condition( Expression.Equal( builderProperty, - Expression.Constant(null, typeof(TBuilder15204))), - Expression.Constant(null, typeof(TCity15204)), + Expression.Constant(null, typeof(MyContext15204.TBuilder15204))), + Expression.Constant(null, typeof(MyContext15204.TCity15204)), cityProperty), - Expression.Constant(null, typeof(TCity15204))), + Expression.Constant(null, typeof(MyContext15204.TCity15204))), Expression.Constant(null, typeof(string)), nameProperty), Expression.Constant("Leeds", typeof(string))), userParam); - using var context = new MyContext15204(_options); var query = context.BuildingSet .Where(selection) .Include(a => a.Builder).ThenInclude(a => a.City) @@ -4929,21 +4468,32 @@ FROM [BuildingSet] AS [b] } } - private SqlServerTestStore CreateDatabase15204() - => CreateTestStore( - () => new MyContext15204(_options), - context => - { - var london = new TCity15204 { Name = "London" }; - var sam = new TBuilder15204 { Name = "Sam", City = london }; + protected class MyContext15204 : DbContext + { + public DbSet MandatorSet { get; set; } + public DbSet BuildingSet { get; set; } + public DbSet Builder { get; set; } + public DbSet City { get; set; } + + public MyContext15204(DbContextOptions options) + : base(options) + { + ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; + ChangeTracker.AutoDetectChangesEnabled = false; + } + + public void Seed() + { + var london = new TCity15204 { Name = "London" }; + var sam = new TBuilder15204 { Name = "Sam", City = london }; - context.MandatorSet.Add( - new TMandator15204 + MandatorSet.Add( + new TMandator15204 + { + Identity = Guid.NewGuid(), + Name = "One", + Buildings = new List { - Identity = Guid.NewGuid(), - Name = "One", - Buildings = new List - { new TBuilding15204 { Identity = Guid.NewGuid(), @@ -4956,15 +4506,15 @@ private SqlServerTestStore CreateDatabase15204() LongName = "One L2", Builder = sam } - } - }); - context.MandatorSet.Add( - new TMandator15204 + } + }); + MandatorSet.Add( + new TMandator15204 + { + Identity = Guid.NewGuid(), + Name = "Two", + Buildings = new List { - Identity = Guid.NewGuid(), - Name = "Two", - Buildings = new List - { new TBuilding15204 { Identity = Guid.NewGuid(), @@ -4977,74 +4527,59 @@ private SqlServerTestStore CreateDatabase15204() LongName = "Two L2", Builder = new TBuilder15204 { Name = "Mark", City = new TCity15204 { Name = "Leeds" } } } - } - }); + } + }); - context.SaveChanges(); + SaveChanges(); + } - ClearLog(); - }); + public class TBuilding15204 + { + public int Id { get; set; } + public Guid Identity { get; set; } + public string LongName { get; set; } + public int BuilderId { get; set; } + public TBuilder15204 Builder { get; set; } + public TMandator15204 Mandator { get; set; } + public int MandatorId { get; set; } + } - private class MyContext15204 : DbContext - { - public DbSet MandatorSet { get; set; } - public DbSet BuildingSet { get; set; } - public DbSet Builder { get; set; } - public DbSet City { get; set; } - - public MyContext15204(DbContextOptions options) - : base(options) + public class TBuilder15204 { - ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; - ChangeTracker.AutoDetectChangesEnabled = false; + public int Id { get; set; } + public string Name { get; set; } + public int CityId { get; set; } + public TCity15204 City { get; set; } } - } - - private class TBuilding15204 - { - public int Id { get; set; } - public Guid Identity { get; set; } - public string LongName { get; set; } - public int BuilderId { get; set; } - public TBuilder15204 Builder { get; set; } - public TMandator15204 Mandator { get; set; } - public int MandatorId { get; set; } - } - private class TBuilder15204 - { - public int Id { get; set; } - public string Name { get; set; } - public int CityId { get; set; } - public TCity15204 City { get; set; } - } - - private class TCity15204 - { - public int Id { get; set; } - public string Name { get; set; } - } + public class TCity15204 + { + public int Id { get; set; } + public string Name { get; set; } + } - private class TMandator15204 - { - public int Id { get; set; } - public Guid Identity { get; set; } - public string Name { get; set; } - public virtual ICollection Buildings { get; set; } + public class TMandator15204 + { + public int Id { get; set; } + public Guid Identity { get; set; } + public string Name { get; set; } + public virtual ICollection Buildings { get; set; } + } } #endregion - #region Bug15518 + #region Issue15518 [ConditionalTheory] [InlineData(false)] [InlineData(true)] - public virtual void Nested_queries_does_not_cause_concurrency_exception_sync(bool tracking) + public virtual async Task Nested_queries_does_not_cause_concurrency_exception_sync(bool tracking) { - using (CreateDatabase15518()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext15518(_options); var query = context.Repos.OrderBy(r => r.Id).Where(r => r.Id > 0); query = tracking ? query.AsTracking() : query.AsNoTracking(); @@ -5055,16 +4590,9 @@ public virtual void Nested_queries_does_not_cause_concurrency_exception_sync(boo } } } - } - [ConditionalTheory] - [InlineData(false)] - [InlineData(true)] - public virtual async Task Nested_queries_does_not_cause_concurrency_exception_async(bool tracking) - { - using (CreateDatabase15518()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext15518(_options); var query = context.Repos.OrderBy(r => r.Id).Where(r => r.Id > 0); query = tracking ? query.AsTracking() : query.AsNoTracking(); @@ -5077,21 +4605,7 @@ public virtual async Task Nested_queries_does_not_cause_concurrency_exception_as } } - private SqlServerTestStore CreateDatabase15518() - => CreateTestStore( - () => new MyContext15518(_options), - context => - { - context.AddRange( - new Repo15518 { Name = "London" }, - new Repo15518 { Name = "New York" }); - - context.SaveChanges(); - - ClearLog(); - }); - - private class MyContext15518 : DbContext + protected class MyContext15518 : DbContext { public DbSet Repos { get; set; } @@ -5099,26 +4613,36 @@ public MyContext15518(DbContextOptions options) : base(options) { } - } - private class Repo15518 - { - public int Id { get; set; } - public string Name { get; set; } + public void Seed() + { + AddRange( + new Repo15518 { Name = "London" }, + new Repo15518 { Name = "New York" }); + + SaveChanges(); + } + + public class Repo15518 + { + public int Id { get; set; } + public string Name { get; set; } + } } #endregion - #region Bug8864 + #region Issue8864 [ConditionalFact] - public virtual void Select_nested_projection() + public virtual async Task Select_nested_projection() { - using (CreateDatabase8864()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext8864(_options); var customers = context.Customers - .Select(c => new { Customer = c, CustomerAgain = Get(context, c.Id) }) + .Select(c => new { Customer = c, CustomerAgain = MyContext8864.Get(context, c.Id) }) .ToList(); Assert.Equal(2, customers.Count); @@ -5130,24 +4654,8 @@ public virtual void Select_nested_projection() } } - private static Customer8864 Get(MyContext8864 context, int id) - => context.Customers.Single(c => c.Id == id); - private SqlServerTestStore CreateDatabase8864() - => CreateTestStore( - () => new MyContext8864(_options), - context => - { - context.AddRange( - new Customer8864 { Name = "Alan" }, - new Customer8864 { Name = "Elon" }); - - context.SaveChanges(); - - ClearLog(); - }); - - private class MyContext8864 : DbContext + protected class MyContext8864 : DbContext { public DbSet Customers { get; set; } @@ -5155,25 +4663,38 @@ public MyContext8864(DbContextOptions options) : base(options) { } - } - private class Customer8864 - { - public int Id { get; set; } - public string Name { get; set; } + public void Seed() + { + AddRange( + new Customer8864 { Name = "Alan" }, + new Customer8864 { Name = "Elon" }); + + SaveChanges(); + } + + public static Customer8864 Get(MyContext8864 context, int id) + => context.Customers.Single(c => c.Id == id); + + public class Customer8864 + { + public int Id { get; set; } + public string Name { get; set; } + } } #endregion - #region Bug7983 + #region Issue7983 [ConditionalFact] - public virtual void New_instances_in_projection_are_not_shared_across_results() + public virtual async Task New_instances_in_projection_are_not_shared_across_results() { - using (CreateDatabase7983()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext7983(_options); - var list = context.Posts.Select(p => new PostDTO7983().From(p)).ToList(); + var list = context.Posts.Select(p => new MyContext7983.PostDTO7983().From(p)).ToList(); Assert.Equal(3, list.Count); Assert.Equal(new[] { "First", "Second", "Third" }, list.Select(dto => dto.Title)); @@ -5184,28 +4705,7 @@ public virtual void New_instances_in_projection_are_not_shared_across_results() } } - private SqlServerTestStore CreateDatabase7983() - => CreateTestStore( - () => new MyContext7983(_options), - context => - { - context.Add( - new Blog7983 - { - Posts = new List - { - new Post7983 { Title = "First" }, - new Post7983 { Title = "Second" }, - new Post7983 { Title = "Third" } - } - }); - - context.SaveChanges(); - - ClearLog(); - }); - - private class MyContext7983 : DbContext + protected class MyContext7983 : DbContext { public DbSet Blogs { get; set; } public DbSet Posts { get; set; } @@ -5214,46 +4714,62 @@ public MyContext7983(DbContextOptions options) : base(options) { } - } - private class Blog7983 - { - public int Id { get; set; } - public string Title { get; set; } + public void Seed() + { + Add(new Blog7983 + { + Posts = new List + { + new Post7983 { Title = "First" }, + new Post7983 { Title = "Second" }, + new Post7983 { Title = "Third" } + } + }); - public ICollection Posts { get; set; } - } + SaveChanges(); + } - private class Post7983 - { - public int Id { get; set; } - public string Title { get; set; } + public class Blog7983 + { + public int Id { get; set; } + public string Title { get; set; } - public int? BlogId { get; set; } - public Blog7983 Blog { get; set; } - } + public ICollection Posts { get; set; } + } - private class PostDTO7983 - { - public string Title { get; set; } + public class Post7983 + { + public int Id { get; set; } + public string Title { get; set; } + + public int? BlogId { get; set; } + public Blog7983 Blog { get; set; } + } - public PostDTO7983 From(Post7983 post) + public class PostDTO7983 { - Title = post.Title; - return this; + public string Title { get; set; } + + public PostDTO7983 From(Post7983 post) + { + Title = post.Title; + return this; + } } } #endregion - #region Bug17253 + #region Issue17253 [ConditionalFact] - public virtual void Self_reference_in_query_filter_works() + public virtual async Task Self_reference_in_query_filter_works() { - using (CreateDatabase17253()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext17253(_options); var query = context.EntitiesWithQueryFilterSelfReference.Where(e => e.Name != "Foo"); var result = query.ToList(); @@ -5263,15 +4779,11 @@ FROM [EntitiesWithQueryFilterSelfReference] AS [e] WHERE EXISTS ( SELECT 1 FROM [EntitiesWithQueryFilterSelfReference] AS [e0]) AND (([e].[Name] <> N'Foo') OR [e].[Name] IS NULL)"); + ClearLog(); } - } - [ConditionalFact] - public virtual void Self_reference_in_query_filter_works_when_nested() - { - using (CreateDatabase17253()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext17253(_options); var query = context.EntitiesReferencingEntityWithQueryFilterSelfReference.Where(e => e.Name != "Foo"); var result = query.ToList(); @@ -5287,7 +4799,7 @@ SELECT 1 } } - private class MyContext17253 : DbContext + protected class MyContext17253 : DbContext { public DbSet EntitiesWithQueryFilterSelfReference { get; set; } @@ -5316,87 +4828,79 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity().HasQueryFilter(e => Set().Any()); modelBuilder.Entity().HasQueryFilter(e => EntitiesWithQueryFilterCycle1.Any()); } - } - - private SqlServerTestStore CreateDatabase17253() - => CreateTestStore( - () => new MyContext17253(_options), - context => - { - context.EntitiesWithQueryFilterSelfReference.Add( - new EntityWithQueryFilterSelfReference { Name = "EntityWithQueryFilterSelfReference" }); - context.EntitiesReferencingEntityWithQueryFilterSelfReference.Add( - new EntityReferencingEntityWithQueryFilterSelfReference - { - Name = "EntityReferencingEntityWithQueryFilterSelfReference" - }); - context.EntitiesWithQueryFilterCycle1.Add(new EntityWithQueryFilterCycle1 { Name = "EntityWithQueryFilterCycle1_1" }); - context.EntitiesWithQueryFilterCycle2.Add(new EntityWithQueryFilterCycle2 { Name = "EntityWithQueryFilterCycle2_1" }); - context.EntitiesWithQueryFilterCycle3.Add(new EntityWithQueryFilterCycle3 { Name = "EntityWithQueryFilterCycle3_1" }); + public void Seed() + { + EntitiesWithQueryFilterSelfReference.Add( + new EntityWithQueryFilterSelfReference { Name = "EntityWithQueryFilterSelfReference" }); + EntitiesReferencingEntityWithQueryFilterSelfReference.Add( + new EntityReferencingEntityWithQueryFilterSelfReference + { + Name = "EntityReferencingEntityWithQueryFilterSelfReference" + }); - context.SaveChanges(); + EntitiesWithQueryFilterCycle1.Add(new EntityWithQueryFilterCycle1 { Name = "EntityWithQueryFilterCycle1_1" }); + EntitiesWithQueryFilterCycle2.Add(new EntityWithQueryFilterCycle2 { Name = "EntityWithQueryFilterCycle2_1" }); + EntitiesWithQueryFilterCycle3.Add(new EntityWithQueryFilterCycle3 { Name = "EntityWithQueryFilterCycle3_1" }); - ClearLog(); - }); + SaveChanges(); + } - private class EntityWithQueryFilterSelfReference - { - public int Id { get; set; } - public string Name { get; set; } - } + public class EntityWithQueryFilterSelfReference + { + public int Id { get; set; } + public string Name { get; set; } + } - private class EntityReferencingEntityWithQueryFilterSelfReference - { - public int Id { get; set; } - public string Name { get; set; } - } + public class EntityReferencingEntityWithQueryFilterSelfReference + { + public int Id { get; set; } + public string Name { get; set; } + } - private class EntityWithQueryFilterCycle1 - { - public int Id { get; set; } - public string Name { get; set; } - } + public class EntityWithQueryFilterCycle1 + { + public int Id { get; set; } + public string Name { get; set; } + } - private class EntityWithQueryFilterCycle2 - { - public int Id { get; set; } - public string Name { get; set; } - } + public class EntityWithQueryFilterCycle2 + { + public int Id { get; set; } + public string Name { get; set; } + } - private class EntityWithQueryFilterCycle3 - { - public int Id { get; set; } - public string Name { get; set; } + public class EntityWithQueryFilterCycle3 + { + public int Id { get; set; } + public string Name { get; set; } + } } #endregion - #region Bug17276_17099_16759 + #region Issue17276_17099_16759 [ConditionalFact] - public virtual void Expression_tree_constructed_via_interface_works_17276() + public virtual async Task Expression_tree_constructed_via_interface_works_17276() { - using (CreateDatabase17276()) + var contextFactory = await InitializeAsync(); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext17276(_options); - var query = List17276(context.RemovableEntities); + var query = MyContext17276.List17276(context.RemovableEntities); AssertSql( @"SELECT [r].[Id], [r].[IsRemoved], [r].[Removed], [r].[RemovedByUser], [r].[OwnedEntity_OwnedValue] FROM [RemovableEntities] AS [r] WHERE [r].[IsRemoved] = CAST(0 AS bit)"); + ClearLog(); } - } - [ConditionalFact] - public virtual void Expression_tree_constructed_via_interface_for_navigation_works_17099() - { - using (CreateDatabase17276()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext17276(_options); var query = context.Parents - .Where(p => EF.Property(EF.Property(p, "RemovableEntity"), "IsRemoved")) + .Where(p => EF.Property(EF.Property(p, "RemovableEntity"), "IsRemoved")) .ToList(); AssertSql( @@ -5404,34 +4908,27 @@ public virtual void Expression_tree_constructed_via_interface_for_navigation_wor FROM [Parents] AS [p] LEFT JOIN [RemovableEntities] AS [r] ON [p].[RemovableEntityId] = [r].[Id] WHERE [r].[IsRemoved] = CAST(1 AS bit)"); + ClearLog(); } - } - [ConditionalFact] - public virtual void Expression_tree_constructed_via_interface_for_owned_navigation_works_17505() - { - using (CreateDatabase17276()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext17276(_options); var query = context.RemovableEntities - .Where(p => EF.Property(EF.Property(p, "OwnedEntity"), "OwnedValue") == "Abc") + .Where(p => EF.Property(EF.Property(p, "OwnedEntity"), "OwnedValue") == "Abc") .ToList(); AssertSql( @"SELECT [r].[Id], [r].[IsRemoved], [r].[Removed], [r].[RemovedByUser], [r].[OwnedEntity_OwnedValue] FROM [RemovableEntities] AS [r] WHERE [r].[OwnedEntity_OwnedValue] = N'Abc'"); + ClearLog(); } - } - [ConditionalFact] - public virtual void Expression_tree_constructed_via_interface_works_16759() - { - using (CreateDatabase17276()) + // #16759 + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext17276(_options); - var specification = new Specification17276(1); - var entities = context.Set().Where(specification.Criteria).ToList(); + var specification = new MyContext17276.Specification17276(1); + var entities = context.Set().Where(specification.Criteria).ToList(); AssertSql( @"@__id_0='1' @@ -5442,7 +4939,7 @@ FROM [Parents] AS [p] } } - private class MyContext17276 : DbContext + protected class MyContext17276 : DbContext { public DbSet RemovableEntities { get; set; } public DbSet Parents { get; set; } @@ -5452,107 +4949,95 @@ public MyContext17276(DbContextOptions options) { } - protected override void OnModelCreating(ModelBuilder modelBuilder) + public static List List17276(IQueryable query) + where T : IRemovable17276 { + return query.Where(x => !x.IsRemoved).ToList(); } - } - - private SqlServerTestStore CreateDatabase17276() - => CreateTestStore( - () => new MyContext17276(_options), - context => - { - context.SaveChanges(); - - ClearLog(); - }); - - private static List List17276(IQueryable query) - where T : IRemovable17276 - { - return query.Where(x => !x.IsRemoved).ToList(); - } - private interface IRemovable17276 - { - bool IsRemoved { get; set; } - - string RemovedByUser { get; set; } + public interface IRemovable17276 + { + bool IsRemoved { get; set; } - DateTime? Removed { get; set; } - } + string RemovedByUser { get; set; } - private class RemovableEntity17276 : IRemovable17276 - { - public int Id { get; set; } - public bool IsRemoved { get; set; } - public string RemovedByUser { get; set; } - public DateTime? Removed { get; set; } - public OwnedEntity OwnedEntity { get; set; } - } + DateTime? Removed { get; set; } + } - private class Parent17276 : IHasId17276 - { - public int Id { get; set; } - public RemovableEntity17276 RemovableEntity { get; set; } - } + public class RemovableEntity17276 : IRemovable17276 + { + public int Id { get; set; } + public bool IsRemoved { get; set; } + public string RemovedByUser { get; set; } + public DateTime? Removed { get; set; } + public OwnedEntity OwnedEntity { get; set; } + } - [Owned] - private class OwnedEntity : IOwned - { - public string OwnedValue { get; set; } - } + public class Parent17276 : IHasId17276 + { + public int Id { get; set; } + public RemovableEntity17276 RemovableEntity { get; set; } + } - private interface IHasId17276 - { - T Id { get; } - } + [Owned] + public class OwnedEntity : IOwned + { + public string OwnedValue { get; set; } + } - private interface IOwned - { - string OwnedValue { get; } - } + public interface IHasId17276 + { + T Id { get; } + } - private class Specification17276 - where T : IHasId17276 - { - public Expression> Criteria { get; } + public interface IOwned + { + string OwnedValue { get; } + } - public Specification17276(int id) + public class Specification17276 + where T : IHasId17276 { - Criteria = t => t.Id == id; + public Expression> Criteria { get; } + + public Specification17276(int id) + { + Criteria = t => t.Id == id; + } } } #endregion - #region Bug6864 + #region Issue6864 [ConditionalFact] - public virtual void Implicit_cast_6864() + public virtual async Task Implicit_cast_6864() { - using (CreateDatabase6864()) + var contextFactory = await InitializeAsync(); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext6864(_options); // Verify no client eval - var query = context.Foos.Where(f => f.String == new Bar6864(1337)).ToList(); + var result = context.Foos.Where(f => f.String == new MyContext6864.Bar6864(1337)).ToList(); + + Assert.Empty(result); AssertSql( @"SELECT [f].[Id], [f].[String] FROM [Foos] AS [f] WHERE [f].[String] = N'1337'"); + ClearLog(); } - } - [ConditionalFact] - public virtual void Access_property_of_closure_6864() - { - using (CreateDatabase6864()) + //Access_property_of_closure + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext6864(_options); // Verify no client eval - var bar = new Bar6864(1337); - var query = context.Foos.Where(f => f.String == bar.Value).ToList(); + var bar = new MyContext6864.Bar6864(1337); + var result = context.Foos.Where(f => f.String == bar.Value).ToList(); + + Assert.Empty(result); AssertSql( @"@__bar_Value_0='1337' (Size = 4000) @@ -5560,18 +5045,17 @@ public virtual void Access_property_of_closure_6864() SELECT [f].[Id], [f].[String] FROM [Foos] AS [f] WHERE [f].[String] = @__bar_Value_0"); + ClearLog(); } - } - [ConditionalFact] - public virtual void Call_method_on_closure_6864() - { - using (CreateDatabase6864()) + //Implicitly_cast_closure + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext6864(_options); // Verify no client eval - var bar = new Bar6864(1337); - var query = context.Foos.Where(f => f.String == bar.ToString()).ToList(); + var bar = new MyContext6864.Bar6864(1337); + var result = context.Foos.Where(f => f.String == bar.ToString()).ToList(); + + Assert.Empty(result); AssertSql( @"@__ToString_0='1337' (Size = 4000) @@ -5579,18 +5063,17 @@ public virtual void Call_method_on_closure_6864() SELECT [f].[Id], [f].[String] FROM [Foos] AS [f] WHERE [f].[String] = @__ToString_0"); + ClearLog(); } - } - [ConditionalFact] - public virtual void Implicitly_cast_closure_6864() - { - using (CreateDatabase6864()) + //Implicitly_cast_closure + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext6864(_options); // Verify no client eval - var bar = new Bar6864(1337); - var query = context.Foos.Where(f => f.String == bar).ToList(); + var bar = new MyContext6864.Bar6864(1337); + var result = context.Foos.Where(f => f.String == bar).ToList(); + + Assert.Empty(result); AssertSql( @"@__p_0='1337' (Size = 4000) @@ -5598,17 +5081,16 @@ public virtual void Implicitly_cast_closure_6864() SELECT [f].[Id], [f].[String] FROM [Foos] AS [f] WHERE [f].[String] = @__p_0"); + ClearLog(); } - } - [ConditionalFact] - public virtual void Implicitly_cast_return_value_6864() - { - using (CreateDatabase6864()) + // Implicitly_cast_return_value + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext6864(_options); // Verify no client eval - var query = context.Foos.Where(f => f.String == new Bar6864(1337).Clone()).ToList(); + var result = context.Foos.Where(f => f.String == new MyContext6864.Bar6864(1337).Clone()).ToList(); + + Assert.Empty(result); AssertSql( @"SELECT [f].[Id], [f].[String] @@ -5625,58 +5107,49 @@ public MyContext6864(DbContextOptions options) : base(options) { } - } - - private SqlServerTestStore CreateDatabase6864() - => CreateTestStore( - () => new MyContext6864(_options), - context => - { - context.SaveChanges(); - ClearLog(); - }); - - private class FooEntity6864 - { - public int Id { get; set; } - public string String { get; set; } - } - - private class Bar6864 - { - private readonly int _value; - - public Bar6864(int value) + public class FooEntity6864 { - _value = value; + public int Id { get; set; } + public string String { get; set; } } - public string Value - => _value.ToString(); + public class Bar6864 + { + private readonly int _value; + + public Bar6864(int value) + { + _value = value; + } - public override string ToString() - => Value; + public string Value + => _value.ToString(); - public static implicit operator string(Bar6864 bar) - => bar.Value; + public override string ToString() + => Value; - public Bar6864 Clone() - => new Bar6864(_value); + public static implicit operator string(Bar6864 bar) + => bar.Value; + + public Bar6864 Clone() + => new Bar6864(_value); + } } #endregion - #region Bug9582 + #region Issue9582 [ConditionalFact] - public virtual void Setting_IsUnicode_generates_unicode_literal_in_SQL() + public virtual async Task Setting_IsUnicode_generates_unicode_literal_in_SQL() { - using (CreateDatabase9582()) + var contextFactory = await InitializeAsync(); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext9582(_options); // Verify SQL - var query = context.Set().Where(xx => xx.Nombre.Contains("lla")).ToList(); + var query = context.Set().Where(xx => xx.Nombre.Contains("lla")).ToList(); AssertSql( @"SELECT [t].[Id], [t].[Nombre] @@ -5685,7 +5158,7 @@ FROM [TipoServicio9582] AS [t] } } - private class MyContext9582 : DbContext + protected class MyContext9582 : DbContext { public MyContext9582(DbContextOptions options) : base(options) @@ -5709,60 +5182,42 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) property.SetIsUnicode(false); } } - } - private SqlServerTestStore CreateDatabase9582() - => CreateTestStore( - () => new MyContext9582(_options), - context => - { - context.SaveChanges(); - - ClearLog(); - }); - - private class TipoServicio9582 - { - public int Id { get; set; } - public string Nombre { get; set; } + public class TipoServicio9582 + { + public int Id { get; set; } + public string Nombre { get; set; } + } } #endregion - #region Bug7222 + #region Issue7222 [ConditionalFact] - public virtual void Inlined_dbcontext_is_not_leaking() + public virtual async Task Inlined_dbcontext_is_not_leaking() { - using (CreateDatabase7222()) + var contextFactory = await InitializeAsync(); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext7222(_options); var entities = context.Blogs.Select(b => context.ClientMethod(b)).ToList(); AssertSql( @"SELECT [b].[Id] FROM [Blogs] AS [b]"); } - } - [ConditionalFact] - public virtual void Implicit_DbContext_throws_memory_leak() - { - using (CreateDatabase7222()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext7222(_options); Assert.Throws(() => context.RunQuery()); } } - private class MyContext7222 : DbContext + protected class MyContext7222 : DbContext { public DbSet Blogs { get; set; } - public MyContext7222() - { - } - public MyContext7222(DbContextOptions options) : base(options) { @@ -5775,124 +5230,95 @@ public void RunQuery() public int ClientMethod(Blog7222 blog) => blog.Id; - } - private SqlServerTestStore CreateDatabase7222() - => CreateTestStore( - () => new MyContext7222(_options), - context => - { - context.SaveChanges(); - - ClearLog(); - }); - - private class Blog7222 - { - public int Id { get; set; } + public class Blog7222 + { + public int Id { get; set; } + } } #endregion - #region Bug17644 + #region Issue17644 [ConditionalFact] - public virtual async Task Return_type_of_First_is_preserved() + public virtual async Task Return_type_of_singular_operator_is_preserved() { - using (CreateDatabase17644()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext17644(_options); var personsToFind = await context.Persons.Where(p => p.Age >= 21) - .Select(p => new PersonDetailView17644 { Name = p.Name, Age = p.Age }) - .FirstAsync(); + .Select(p => new MyContext17644.PersonDetailView17644 { Name = p.Name, Age = p.Age }) + .FirstAsync(); AssertSql( @"SELECT TOP(1) [p].[Name], [p].[Age] FROM [Persons] AS [p] WHERE [p].[Age] >= 21"); + ClearLog(); } - } - [ConditionalFact] - public virtual async Task Return_type_of_FirstOrDefault_is_preserved() - { - using (CreateDatabase17644()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext17644(_options); var personsToFind = await context.Persons.Where(p => p.Age >= 21) - .Select(p => new PersonDetailView17644 { Name = p.Name, Age = p.Age }) - .FirstOrDefaultAsync(); + .Select(p => new MyContext17644.PersonDetailView17644 { Name = p.Name, Age = p.Age }) + .FirstOrDefaultAsync(); AssertSql( @"SELECT TOP(1) [p].[Name], [p].[Age] FROM [Persons] AS [p] WHERE [p].[Age] >= 21"); + ClearLog(); } - } - [ConditionalFact] - public virtual async Task Return_type_of_Single_is_preserved() - { - using (CreateDatabase17644()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext17644(_options); var personsToFind = await context.Persons.Where(p => p.Age >= 21) - .Select(p => new PersonDetailView17644 { Name = p.Name, Age = p.Age }) - .SingleAsync(); + .Select(p => new MyContext17644.PersonDetailView17644 { Name = p.Name, Age = p.Age }) + .SingleAsync(); AssertSql( @"SELECT TOP(2) [p].[Name], [p].[Age] FROM [Persons] AS [p] WHERE [p].[Age] >= 21"); + ClearLog(); } - } - [ConditionalFact] - public virtual async Task Return_type_of_SingleOrDefault_is_preserved() - { - using (CreateDatabase17644()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext17644(_options); var personsToFind = await context.Persons.Where(p => p.Age >= 21) - .Select(p => new PersonDetailView17644 { Name = p.Name, Age = p.Age }) - .SingleOrDefaultAsync(); + .Select(p => new MyContext17644.PersonDetailView17644 { Name = p.Name, Age = p.Age }) + .SingleOrDefaultAsync(); AssertSql( @"SELECT TOP(2) [p].[Name], [p].[Age] FROM [Persons] AS [p] WHERE [p].[Age] >= 21"); + ClearLog(); } - } - [ConditionalFact] - public virtual async Task Return_type_of_Last_is_preserved() - { - using (CreateDatabase17644()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext17644(_options); var personsToFind = await context.Persons.Where(p => p.Age >= 21) .OrderBy(p => p.Id) - .Select(p => new PersonDetailView17644 { Name = p.Name, Age = p.Age }) - .LastAsync(); + .Select(p => new MyContext17644.PersonDetailView17644 { Name = p.Name, Age = p.Age }) + .LastAsync(); AssertSql( @"SELECT TOP(1) [p].[Name], [p].[Age] FROM [Persons] AS [p] WHERE [p].[Age] >= 21 ORDER BY [p].[Id] DESC"); + ClearLog(); } - } - [ConditionalFact] - public virtual async Task Return_type_of_LastOrDefault_is_preserved() - { - using (CreateDatabase17644()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext17644(_options); var personsToFind = await context.Persons.Where(p => p.Age >= 21) .OrderBy(p => p.Id) - .Select(p => new PersonDetailView17644 { Name = p.Name, Age = p.Age }) - .LastOrDefaultAsync(); + .Select(p => new MyContext17644.PersonDetailView17644 { Name = p.Name, Age = p.Age }) + .LastOrDefaultAsync(); AssertSql( @"SELECT TOP(1) [p].[Name], [p].[Age] @@ -5902,59 +5328,51 @@ FROM [Persons] AS [p] } } - private class MyContext17644 : DbContext + protected class MyContext17644 : DbContext { public DbSet Persons { get; set; } - public MyContext17644() - { - } - public MyContext17644(DbContextOptions options) : base(options) { } - } - - private SqlServerTestStore CreateDatabase17644() - => CreateTestStore( - () => new MyContext17644(_options), - context => - { - var person = new Person17644 { Name = "John Doe", Age = 21 }; - context.Persons.Add(person); - context.SaveChanges(); - ClearLog(); - }); + public void Seed() + { + var person = new Person17644 { Name = "John Doe", Age = 21 }; + Persons.Add(person); + SaveChanges(); + } - private class Person17644 - { - public int Id { get; set; } - public string Name { set; get; } - public int Age { set; get; } - } + public class Person17644 + { + public int Id { get; set; } + public string Name { set; get; } + public int Age { set; get; } + } - private class PersonView17644 - { - public string Name { set; get; } - } + public class PersonView17644 + { + public string Name { set; get; } + } - private class PersonDetailView17644 : PersonView17644 - { - public int Age { set; get; } + public class PersonDetailView17644 : PersonView17644 + { + public int Age { set; get; } + } } #endregion - #region Bug11023 + #region Issue11023 [ConditionalFact] public virtual async Task Async_correlated_projection_with_first() { - using (CreateDatabase11023()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext11023(_options); var query = await context.Entities .Select(e => new { ThingIds = e.Values.First().Things.Select(t => t.Subthing.ThingId).ToList() }) .ToListAsync(); @@ -5984,7 +5402,7 @@ FROM [Values] AS [v0] } } - private class MyContext11023 : DbContext + protected class MyContext11023 : DbContext { public DbSet Entities { get; set; } public DbSet Values { get; set; } @@ -5995,18 +5413,13 @@ public MyContext11023(DbContextOptions options) : base(options) { } - } - private SqlServerTestStore CreateDatabase11023() - => CreateTestStore( - () => new MyContext11023(_options), - context => - { - context.Add( - new Entity11023 + public void Seed() + { + Add(new Entity11023 + { + Values = new List { - Values = new List - { new Value11023 { Things = new List @@ -6015,37 +5428,36 @@ private SqlServerTestStore CreateDatabase11023() new Thing11023 { Subthing = new Subthing11023() } } } - } - }); - - context.SaveChanges(); + } + }); - ClearLog(); - }); + SaveChanges(); + } - private class Entity11023 - { - public int Id { get; set; } - public ICollection Values { get; set; } - } + public class Entity11023 + { + public int Id { get; set; } + public ICollection Values { get; set; } + } - private class Value11023 - { - public int Id { get; set; } - public ICollection Things { get; set; } - } + public class Value11023 + { + public int Id { get; set; } + public ICollection Things { get; set; } + } - private class Thing11023 - { - public int Id { get; set; } - public Subthing11023 Subthing { get; set; } - } + public class Thing11023 + { + public int Id { get; set; } + public Subthing11023 Subthing { get; set; } + } - private class Subthing11023 - { - public int Id { get; set; } - public int ThingId { get; set; } - public Thing11023 Thing { get; set; } + public class Subthing11023 + { + public int Id { get; set; } + public int ThingId { get; set; } + public Thing11023 Thing { get; set; } + } } #endregion @@ -6053,11 +5465,12 @@ private class Subthing11023 #region Issue7973 [ConditionalFact] - public virtual void SelectMany_with_collection_selector_having_subquery() + public virtual async Task SelectMany_with_collection_selector_having_subquery() { - using (CreateDatabase7973()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext7973(_options); var users = (from user in context.Users from organisation in context.Organisations.Where(o => o.OrganisationUsers.Any()).DefaultIfEmpty() select new { UserId = user.Id, OrgId = organisation.Id }).ToList(); @@ -6084,7 +5497,7 @@ FROM [OrganisationUser7973] AS [o0] } } - private class MyContext7973 : DbContext + protected class MyContext7973 : DbContext { public DbSet Users { get; set; } public DbSet Organisations { get; set; } @@ -6102,41 +5515,37 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity().HasOne(ou => ou.User).WithMany(u => u.OrganisationUsers) .HasForeignKey(ou => ou.UserId); } - } - private SqlServerTestStore CreateDatabase7973() - => CreateTestStore( - () => new MyContext7973(_options), - context => - { - context.AddRange( - new OrganisationUser7973 { Organisation = new Organisation7973(), User = new User7973() }, - new Organisation7973(), - new User7973()); + public void Seed() + { + AddRange( + new OrganisationUser7973 { Organisation = new Organisation7973(), User = new User7973() }, + new Organisation7973(), + new User7973()); - context.SaveChanges(); - ClearLog(); - }); + SaveChanges(); + } - private class User7973 - { - public int Id { get; set; } - public List OrganisationUsers { get; set; } - } + public class User7973 + { + public int Id { get; set; } + public List OrganisationUsers { get; set; } + } - private class Organisation7973 - { - public int Id { get; set; } - public List OrganisationUsers { get; set; } - } + public class Organisation7973 + { + public int Id { get; set; } + public List OrganisationUsers { get; set; } + } - private class OrganisationUser7973 - { - public int OrganisationId { get; set; } - public Organisation7973 Organisation { get; set; } + public class OrganisationUser7973 + { + public int OrganisationId { get; set; } + public Organisation7973 Organisation { get; set; } - public int UserId { get; set; } - public User7973 User { get; set; } + public int UserId { get; set; } + public User7973 User { get; set; } + } } #endregion @@ -6144,11 +5553,12 @@ private class OrganisationUser7973 #region Issue10447 [ConditionalFact] - public virtual void Nested_include_queries_do_not_populate_navigation_twice() + public virtual async Task Nested_include_queries_do_not_populate_navigation_twice() { - using (CreateDatabase10447()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext10447(_options); var query = context.Blogs.Include(b => b.Posts); foreach (var blog in query) @@ -6164,7 +5574,7 @@ public virtual void Nested_include_queries_do_not_populate_navigation_twice() } } - private class MyContext10447 : DbContext + protected class MyContext10447 : DbContext { public DbSet Blogs { get; set; } @@ -6176,41 +5586,37 @@ public MyContext10447(DbContextOptions options) protected override void OnModelCreating(ModelBuilder modelBuilder) { } - } - private SqlServerTestStore CreateDatabase10447() - => CreateTestStore( - () => new MyContext10447(_options), - context => - { - context.AddRange( - new Blog10447 + public void Seed() + { + AddRange( + new Blog10447 + { + Posts = new List { - Posts = new List - { new Post10447(), new Post10447(), new Post10447() - } - }, - new Blog10447 { Posts = new List { new Post10447(), new Post10447() } }, - new Blog10447 { Posts = new List { new Post10447() } }); + } + }, + new Blog10447 { Posts = new List { new Post10447(), new Post10447() } }, + new Blog10447 { Posts = new List { new Post10447() } }); - context.SaveChanges(); - ClearLog(); - }); + SaveChanges(); + } - private class Blog10447 - { - public int Id { get; set; } - public List Posts { get; set; } - } + public class Blog10447 + { + public int Id { get; set; } + public List Posts { get; set; } + } - private class Post10447 - { - public int Id { get; set; } + public class Post10447 + { + public int Id { get; set; } - public Blog10447 Blog { get; set; } + public Blog10447 Blog { get; set; } + } } #endregion @@ -6218,11 +5624,12 @@ private class Post10447 #region Issue12456 [ConditionalFact] - public virtual void Let_multiple_references_with_reference_to_outer() + public virtual async Task Let_multiple_references_with_reference_to_outer() { - using (CreateDatabase12456()) + var contextFactory = await InitializeAsync(); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext12456(_options); var users = (from a in context.Activities let cs = context.CompetitionSeasons .First(s => s.StartDate <= a.DateTime && a.DateTime < s.EndDate) @@ -6245,15 +5652,11 @@ FROM [CompetitionSeasons] AS [c1] WHERE ([c1].[StartDate] <= [a].[DateTime]) AND ([a].[DateTime] < [c1].[EndDate]))) AND ([a0].[Id] = [a1].[ActivityTypeId]) ) AS [t] ORDER BY [a].[Id], [a0].[Id], [t].[Id], [t].[Id0]"); + ClearLog(); } - } - [ConditionalFact] - public virtual void Let_multiple_references_with_reference_to_outer_2() - { - using (CreateDatabase12456()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext12456(_options); var users = context.Activities .Select( a => new @@ -6299,55 +5702,47 @@ public MyContext12456(DbContextOptions options) : base(options) { } - } - private SqlServerTestStore CreateDatabase12456() - => CreateTestStore( - () => new MyContext12456(_options), - context => - { - ClearLog(); - }); - - private class CompetitionSeason12456 - { - public int Id { get; set; } - public DateTime StartDate { get; set; } - public DateTime EndDate { get; set; } - public List ActivityTypePoints { get; set; } - } + public class CompetitionSeason12456 + { + public int Id { get; set; } + public DateTime StartDate { get; set; } + public DateTime EndDate { get; set; } + public List ActivityTypePoints { get; set; } + } - private class Point12456 - { - public int Id { get; set; } - public CompetitionSeason12456 CompetitionSeason { get; set; } - public int? Points { get; set; } - } + public class Point12456 + { + public int Id { get; set; } + public CompetitionSeason12456 CompetitionSeason { get; set; } + public int? Points { get; set; } + } - private class ActivityType12456 - { - public int Id { get; set; } - public List Points { get; set; } - } + public class ActivityType12456 + { + public int Id { get; set; } + public List Points { get; set; } + } - private class ActivityTypePoints12456 - { - public int Id { get; set; } - public int ActivityTypeId { get; set; } - public int CompetitionSeasonId { get; set; } - public int Points { get; set; } + public class ActivityTypePoints12456 + { + public int Id { get; set; } + public int ActivityTypeId { get; set; } + public int CompetitionSeasonId { get; set; } + public int Points { get; set; } - public ActivityType12456 ActivityType { get; set; } - public CompetitionSeason12456 CompetitionSeason { get; set; } - } + public ActivityType12456 ActivityType { get; set; } + public CompetitionSeason12456 CompetitionSeason { get; set; } + } - private class Activity12456 - { - public int Id { get; set; } - public int ActivityTypeId { get; set; } - public DateTime DateTime { get; set; } - public int? Points { get; set; } - public ActivityType12456 ActivityType { get; set; } + public class Activity12456 + { + public int Id { get; set; } + public int ActivityTypeId { get; set; } + public DateTime DateTime { get; set; } + public int? Points { get; set; } + public ActivityType12456 ActivityType { get; set; } + } } #endregion @@ -6357,9 +5752,10 @@ private class Activity12456 [ConditionalFact] public virtual async Task Max_in_multi_level_nested_subquery() { - using (CreateDatabase15137()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext15137(_options); var container = await context.Trades .Select( x => new @@ -6407,7 +5803,7 @@ FROM [DbTradeAsset] AS [d0] } } - private class MyContext15137 : DbContext + protected class MyContext15137 : DbContext { public DbSet Trades { get; set; } @@ -6415,16 +5811,12 @@ public MyContext15137(DbContextOptions options) : base(options) { } - } - private SqlServerTestStore CreateDatabase15137() - => CreateTestStore( - () => new MyContext15137(_options), - context => + public void Seed() + { + var dbTrade = new DbTrade { - var dbTrade = new DbTrade - { - Assets = new List + Assets = new List { new DbTradeAsset { @@ -6434,48 +5826,47 @@ private SqlServerTestStore CreateDatabase15137() } } } - }; - - context.Trades.Add(dbTrade); - context.SaveChanges(); + }; - ClearLog(); - }); + Trades.Add(dbTrade); + SaveChanges(); + } - private class DbTrade - { - public int Id { get; set; } - public List Assets { get; set; } - } + public class DbTrade + { + public int Id { get; set; } + public List Assets { get; set; } + } - private class DbTradeAsset - { - public int Id { get; set; } - public int ContractId { get; set; } + public class DbTradeAsset + { + public int Id { get; set; } + public int ContractId { get; set; } - public DbContract Contract { get; set; } - } + public DbContract Contract { get; set; } + } - private class DbContract - { - public int Id { get; set; } + public class DbContract + { + public int Id { get; set; } - public DbSeason Season { get; set; } - } + public DbSeason Season { get; set; } + } - private class DbSeason - { - public int Id { get; set; } + public class DbSeason + { + public int Id { get; set; } - public List Games { get; set; } - } + public List Games { get; set; } + } - private class DbGame - { - public int Id { get; set; } - public int GameNumber { get; set; } + public class DbGame + { + public int Id { get; set; } + public int GameNumber { get; set; } - public DbSeason Season { get; set; } + public DbSeason Season { get; set; } + } } #endregion @@ -6483,24 +5874,25 @@ private class DbGame #region Issue13517 [ConditionalFact] - public void Query_filter_with_pk_fk_optimization_bug_13517() + public async Task Query_filter_with_pk_fk_optimization_Issue_13517() { - using var _ = CreateDatabase13517(); - using var context = new BugContext13517(_options); + var contextFactory = await InitializeAsync(seed: c => c.Seed()); - context.Entities.Select( - s => - new BugEntityDto13517 - { - Id = s.Id, - RefEntity = s.RefEntity == null - ? null - : new BugRefEntityDto13517 { Id = s.RefEntity.Id, Public = s.RefEntity.Public }, - RefEntityId = s.RefEntityId - }).Single(p => p.Id == 1); + using (var context = contextFactory.CreateContext()) + { + context.Entities.Select( + s => + new IssueContext13517.IssueEntityDto13517 + { + Id = s.Id, + RefEntity = s.RefEntity == null + ? null + : new IssueContext13517.IssueRefEntityDto13517 { Id = s.RefEntity.Id, Public = s.RefEntity.Public }, + RefEntityId = s.RefEntityId + }).Single(p => p.Id == 1); - AssertSql( - @"SELECT TOP(2) [e].[Id], CASE + AssertSql( + @"SELECT TOP(2) [e].[Id], CASE WHEN [t].[Id] IS NULL THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END, [t].[Id], [t].[Public], [e].[RefEntityId] @@ -6511,60 +5903,56 @@ FROM [RefEntities] AS [r] WHERE [r].[Public] = CAST(1 AS bit) ) AS [t] ON [e].[RefEntityId] = [t].[Id] WHERE [e].[Id] = 1"); + } } - private SqlServerTestStore CreateDatabase13517() - => CreateTestStore( - () => new BugContext13517(_options), - context => - { - var refEntity = new BugRefEntity13517 { Public = false }; - context.RefEntities.Add(refEntity); - context.Entities.Add(new BugEntity13517 { RefEntity = refEntity }); - context.SaveChanges(); - - ClearLog(); - }); - - private class BugEntity13517 + protected class IssueContext13517 : DbContext { - public int Id { get; set; } - public int? RefEntityId { get; set; } - public BugRefEntity13517 RefEntity { get; set; } - } + public DbSet Entities { get; set; } + public DbSet RefEntities { get; set; } - private class BugRefEntity13517 - { - public int Id { get; set; } - public bool Public { get; set; } - } + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity().HasQueryFilter(f => f.Public); + } - private class BugEntityDto13517 - { - public int Id { get; set; } - public int? RefEntityId { get; set; } - public BugRefEntityDto13517 RefEntity { get; set; } - } + public IssueContext13517(DbContextOptions options) + : base(options) + { + } - private class BugRefEntityDto13517 - { - public int Id { get; set; } - public bool Public { get; set; } - } + public void Seed() + { + var refEntity = new IssueRefEntity13517 { Public = false }; + RefEntities.Add(refEntity); + Entities.Add(new IssueEntity13517 { RefEntity = refEntity }); + SaveChanges(); + } - private class BugContext13517 : DbContext - { - public DbSet Entities { get; set; } - public DbSet RefEntities { get; set; } + public class IssueEntity13517 + { + public int Id { get; set; } + public int? RefEntityId { get; set; } + public IssueRefEntity13517 RefEntity { get; set; } + } - protected override void OnModelCreating(ModelBuilder modelBuilder) + public class IssueRefEntity13517 { - modelBuilder.Entity().HasQueryFilter(f => f.Public); + public int Id { get; set; } + public bool Public { get; set; } } - public BugContext13517(DbContextOptions options) - : base(options) + public class IssueEntityDto13517 + { + public int Id { get; set; } + public int? RefEntityId { get; set; } + public IssueRefEntityDto13517 RefEntity { get; set; } + } + + public class IssueRefEntityDto13517 { + public int Id { get; set; } + public bool Public { get; set; } } } @@ -6573,18 +5961,19 @@ public BugContext13517(DbContextOptions options) #region Issue17794 [ConditionalFact] - public void Double_convert_interface_created_expression_tree() + public async Task Double_convert_interface_created_expression_tree() { - using var _ = CreateDatabase17794(); - using var context = new BugContext17794(_options); + var contextFactory = await InitializeAsync(seed: c => c.Seed()); - var expression = HasAction17794(OfferActions17794.Accepted); - var query = context.Offers.Where(expression).Count(); + using (var context = contextFactory.CreateContext()) + { + var expression = IssueContext17794.HasAction17794(IssueContext17794.OfferActions17794.Accepted); + var query = context.Offers.Where(expression).Count(); - Assert.Equal(1, query); + Assert.Equal(1, query); - AssertSql( - @"@__action_0='1' + AssertSql( + @"@__action_0='1' SELECT COUNT(*) FROM [Offers] AS [o] @@ -6592,64 +5981,10 @@ WHERE EXISTS ( SELECT 1 FROM [OfferActions] AS [o0] WHERE ([o].[Id] = [o0].[OfferId]) AND ([o0].[Action] = @__action_0))"); + } } - private SqlServerTestStore CreateDatabase17794() - => CreateTestStore( - () => new BugContext17794(_options), - context => - { - context.Add( - new Offer17794 - { - Actions = new List { new OfferAction17794 { Action = OfferActions17794.Accepted } } - }); - - context.SaveChanges(); - - ClearLog(); - }); - - private static Expression> HasAction17794(OfferActions17794 action) - where T : IOffer17794 - { - Expression> predicate = oa => oa.Action == action; - - return v => v.Actions.AsQueryable().Any(predicate); - } - - private interface IOffer17794 - { - ICollection Actions { get; set; } - } - - private class Offer17794 : IOffer17794 - { - public int Id { get; set; } - - public ICollection Actions { get; set; } - } - - private enum OfferActions17794 - { - Accepted = 1, - Declined = 2 - } - - private class OfferAction17794 - { - public int Id { get; set; } - - [Required] - public Offer17794 Offer { get; set; } - - public int OfferId { get; set; } - - [Required] - public OfferActions17794 Action { get; set; } - } - - private class BugContext17794 : DbContext + protected class IssueContext17794 : DbContext { public DbSet Offers { get; set; } public DbSet OfferActions { get; set; } @@ -6658,111 +5993,155 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) { } - public BugContext17794(DbContextOptions options) + public IssueContext17794(DbContextOptions options) : base(options) { } - } - #endregion + public void Seed() + { + Add( + new Offer17794 + { + Actions = new List { new OfferAction17794 { Action = OfferActions17794.Accepted } } + }); - #region Issue18087 + SaveChanges(); + } - [ConditionalFact] - public void Cast_to_implemented_interface_is_removed_from_expression_tree() - { - using var _ = CreateDatabase18087(); - using var context = new BugContext18087(_options); + public static Expression> HasAction17794(OfferActions17794 action) + where T : IOffer17794 + { + Expression> predicate = oa => oa.Action == action; - var queryBase = (IQueryable)context.MockEntities; - var id = 1; - var query = queryBase.Cast().FirstOrDefault(x => x.Id == id); + return v => v.Actions.AsQueryable().Any(predicate); + } - Assert.Equal(1, query.Id); + public interface IOffer17794 + { + ICollection Actions { get; set; } + } - AssertSql( - @"@__id_0='1' + public class Offer17794 : IOffer17794 + { + public int Id { get; set; } -SELECT TOP(1) [m].[Id], [m].[Name], [m].[NavigationEntityId] -FROM [MockEntities] AS [m] -WHERE [m].[Id] = @__id_0"); - } + public ICollection Actions { get; set; } + } - [ConditionalFact] - public void Cast_to_object_is_removed_from_expression_tree() - { - using var _ = CreateDatabase18087(); - using var context = new BugContext18087(_options); + public enum OfferActions17794 + { + Accepted = 1, + Declined = 2 + } - var queryBase = (IQueryable)context.MockEntities; - var query = queryBase.Cast().Count(); + public class OfferAction17794 + { + public int Id { get; set; } - Assert.Equal(3, query); + [Required] + public Offer17794 Offer { get; set; } - AssertSql( - @"SELECT COUNT(*) -FROM [MockEntities] AS [m]"); + public int OfferId { get; set; } + + [Required] + public OfferActions17794 Action { get; set; } + } } + #endregion + + #region Issue18087 + [ConditionalFact] - public void Cast_to_non_implemented_interface_is_not_removed_from_expression_tree() + public async Task Casts_are_removed_from_expression_tree_when_redundant() { - using var _ = CreateDatabase18087(); - using var context = new BugContext18087(_options); + var contextFactory = await InitializeAsync(seed: c => c.Seed()); - var queryBase = (IQueryable)context.MockEntities; - var id = 1; + // implemented_interface + using (var context = contextFactory.CreateContext()) + { + var queryBase = (IQueryable)context.MockEntities; + var id = 1; + var query = queryBase.Cast().FirstOrDefault(x => x.Id == id); - var message = Assert.Throws( - () => queryBase.Cast().FirstOrDefault(x => x.Id == id)).Message; + Assert.Equal(1, query.Id); - Assert.Equal( - CoreStrings.TranslationFailed( - @"DbSet() .Cast() .Where(e => e.Id == __id_0)"), - message.Replace("\r", "").Replace("\n", "")); - } + AssertSql( + @"@__id_0='1' - private SqlServerTestStore CreateDatabase18087() - => CreateTestStore( - () => new BugContext18087(_options), - context => - { - context.AddRange( - new MockEntity { Name = "Entity1", NavigationEntity = null }, - new MockEntity { Name = "Entity2", NavigationEntity = null }, - new MockEntity { Name = "NewEntity", NavigationEntity = null }); +SELECT TOP(1) [m].[Id], [m].[Name], [m].[NavigationEntityId] +FROM [MockEntities] AS [m] +WHERE [m].[Id] = @__id_0"); + ClearLog(); + } - context.SaveChanges(); + // object + using (var context = contextFactory.CreateContext()) + { + var queryBase = (IQueryable)context.MockEntities; + var query = queryBase.Cast().Count(); - ClearLog(); - }); + Assert.Equal(3, query); - private interface IDomainEntity - { - int Id { get; set; } - } + AssertSql( + @"SELECT COUNT(*) +FROM [MockEntities] AS [m]"); + ClearLog(); + } - private interface IDummyEntity - { - int Id { get; set; } - } + // non_implemented_interface + using (var context = contextFactory.CreateContext()) + { + var queryBase = (IQueryable)context.MockEntities; + var id = 1; - private class MockEntity : IDomainEntity - { - public int Id { get; set; } - public string Name { get; set; } + var message = Assert.Throws( + () => queryBase.Cast().FirstOrDefault(x => x.Id == id)).Message; - public MockEntity NavigationEntity { get; set; } + Assert.Equal( + CoreStrings.TranslationFailed( + @"DbSet() .Cast() .Where(e => e.Id == __id_0)"), + message.Replace("\r", "").Replace("\n", "")); + } } - private class BugContext18087 : DbContext + protected class IssueContext18087 : DbContext { - public BugContext18087(DbContextOptions options) + public IssueContext18087(DbContextOptions options) : base(options) { } public DbSet MockEntities { get; set; } + + public void Seed() + { + AddRange( + new MockEntity { Name = "Entity1", NavigationEntity = null }, + new MockEntity { Name = "Entity2", NavigationEntity = null }, + new MockEntity { Name = "NewEntity", NavigationEntity = null }); + + SaveChanges(); + } + + public interface IDomainEntity + { + int Id { get; set; } + } + + public interface IDummyEntity + { + int Id { get; set; } + } + + public class MockEntity : IDomainEntity + { + public int Id { get; set; } + public string Name { get; set; } + + public MockEntity NavigationEntity { get; set; } + } } #endregion @@ -6770,50 +6149,44 @@ public BugContext18087(DbContextOptions options) #region Issue18759 [ConditionalFact] - public void Query_filter_with_null_constant() + public async Task Query_filter_with_null_constant() { - using var _ = CreateDatabase18759(); - using var context = new BugContext18759(_options); + var contextFactory = await InitializeAsync(); - var people = context.People.ToList(); + using (var context = contextFactory.CreateContext()) + { + var people = context.People.ToList(); - AssertSql( - @"SELECT [p].[Id], [p].[UserDeleteId] + AssertSql( + @"SELECT [p].[Id], [p].[UserDeleteId] FROM [People] AS [p] LEFT JOIN [User18759] AS [u] ON [p].[UserDeleteId] = [u].[Id] WHERE [u].[Id] IS NOT NULL"); + } } - private SqlServerTestStore CreateDatabase18759() - => CreateTestStore( - () => new BugContext18759(_options), - context => - { - ClearLog(); - }); - - private class Person18759 - { - public int Id { get; set; } - public User18759 UserDelete { get; set; } - } - - private class User18759 - { - public int Id { get; set; } - } - - private class BugContext18759 : DbContext + protected class IssueContext18759 : DbContext { public DbSet People { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) => modelBuilder.Entity().HasQueryFilter(p => p.UserDelete != null); - public BugContext18759(DbContextOptions options) + public IssueContext18759(DbContextOptions options) : base(options) { } + + public class Person18759 + { + public int Id { get; set; } + public User18759 UserDelete { get; set; } + } + + public class User18759 + { + public int Id { get; set; } + } } #endregion @@ -6821,19 +6194,20 @@ public BugContext18759(DbContextOptions options) #region Issue19138 [ConditionalFact] - public void Accessing_scalar_property_in_derived_type_projection_does_not_load_owned_navigations() + public async Task Accessing_scalar_property_in_derived_type_projection_does_not_load_owned_navigations() { - using var _ = CreateDatabase19138(); - using var context = new BugContext19138(_options); + var contextFactory = await InitializeAsync(seed: c => c.Seed()); - var result = context.BaseEntities - .Select(b => context.OtherEntities.Where(o => o.OtherEntityData == ((SubEntity19138)b).Data).FirstOrDefault()) - .ToList(); + using (var context = contextFactory.CreateContext()) + { + var result = context.BaseEntities + .Select(b => context.OtherEntities.Where(o => o.OtherEntityData == ((IssueContext19138.SubEntity19138)b).Data).FirstOrDefault()) + .ToList(); - Assert.Equal("A", Assert.Single(result).OtherEntityData); + Assert.Equal("A", Assert.Single(result).OtherEntityData); - AssertSql( - @"SELECT [t0].[Id], [t0].[OtherEntityData] + AssertSql( + @"SELECT [t0].[Id], [t0].[OtherEntityData] FROM [BaseEntities] AS [b] LEFT JOIN ( SELECT [t].[Id], [t].[OtherEntityData] @@ -6843,44 +6217,10 @@ FROM [OtherEntities] AS [o] ) AS [t] WHERE [t].[row] <= 1 ) AS [t0] ON [b].[Data] = [t0].[OtherEntityData]"); + } } - private SqlServerTestStore CreateDatabase19138() - => CreateTestStore( - () => new BugContext19138(_options), - context => - { - context.Add(new OtherEntity19138 { OtherEntityData = "A" }); - context.Add(new SubEntity19138 { Data = "A" }); - - context.SaveChanges(); - - ClearLog(); - }); - - private class BaseEntity19138 - { - public int Id { get; set; } - } - - private class SubEntity19138 : BaseEntity19138 - { - public string Data { get; set; } - public Owned19138 Owned { get; set; } - } - - private class Owned19138 - { - public string OwnedData { get; set; } - } - - private class OtherEntity19138 - { - public int Id { get; set; } - public string OtherEntityData { get; set; } - } - - private class BugContext19138 : DbContext + protected class IssueContext19138 : DbContext { public DbSet BaseEntities { get; set; } public DbSet OtherEntities { get; set; } @@ -6892,10 +6232,40 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity(); } - public BugContext19138(DbContextOptions options) + public IssueContext19138(DbContextOptions options) : base(options) { } + + public void Seed() + { + Add(new OtherEntity19138 { OtherEntityData = "A" }); + Add(new SubEntity19138 { Data = "A" }); + + SaveChanges(); + } + + public class BaseEntity19138 + { + public int Id { get; set; } + } + + public class SubEntity19138 : BaseEntity19138 + { + public string Data { get; set; } + public Owned19138 Owned { get; set; } + } + + public class Owned19138 + { + public string OwnedData { get; set; } + } + + public class OtherEntity19138 + { + public int Id { get; set; } + public string OtherEntityData { get; set; } + } } #endregion @@ -6903,84 +6273,62 @@ public BugContext19138(DbContextOptions options) #region Issue19708 [ConditionalFact] - public void GroupJoin_SelectMany_in_query_filter_gets_flattened() + public async Task GroupJoin_SelectMany_gets_flattened() { - using var _ = CreateDatabase19708(); - using var context = new BugContext19708(_options); + var contextFactory = await InitializeAsync(seed: c => c.Seed()); - var query = context.CustomerFilters.ToList(); + using (var context = contextFactory.CreateContext()) + { + var query = context.CustomerFilters.ToList(); - AssertSql( - @"SELECT [c].[CustomerId], [c].[CustomerMembershipId] + AssertSql( + @"SELECT [c].[CustomerId], [c].[CustomerMembershipId] FROM [CustomerFilters] AS [c] WHERE ( SELECT COUNT(*) FROM [Customers] AS [c0] LEFT JOIN [CustomerMemberships] AS [c1] ON [c0].[Id] = [c1].[CustomerId] WHERE [c1].[Id] IS NOT NULL AND ([c0].[Id] = [c].[CustomerId])) > 0"); - } - - [ConditionalFact] - public void GroupJoin_SelectMany_in_defining_query_gets_flattened() - { - using var _ = CreateDatabase19708(); - using var context = new BugContext19708(_options); - - var query = context.Set().ToList(); - - Assert.Collection( - query, - t => AssertCustomerView(t, 1, "First", 1, "FirstChild"), - t => AssertCustomerView(t, 2, "Second", 2, "SecondChild1"), - t => AssertCustomerView(t, 2, "Second", 3, "SecondChild2"), - t => AssertCustomerView(t, 3, "Third", null, "")); + ClearLog(); + } - static void AssertCustomerView( - CustomerView19708 actual, - int id, - string name, - int? customerMembershipId, - string customerMembershipName) + using (var context = contextFactory.CreateContext()) { - Assert.Equal(id, actual.Id); - Assert.Equal(name, actual.Name); - Assert.Equal(customerMembershipId, actual.CustomerMembershipId); - Assert.Equal(customerMembershipName, actual.CustomerMembershipName); - } + var query = context.Set().ToList(); - AssertSql( - @"SELECT [c].[Id], [c].[Name], [c0].[Id] AS [CustomerMembershipId], CASE + Assert.Collection( + query, + t => AssertCustomerView(t, 1, "First", 1, "FirstChild"), + t => AssertCustomerView(t, 2, "Second", 2, "SecondChild1"), + t => AssertCustomerView(t, 2, "Second", 3, "SecondChild2"), + t => AssertCustomerView(t, 3, "Third", null, "")); + + static void AssertCustomerView( + IssueContext19708.CustomerView19708 actual, + int id, + string name, + int? customerMembershipId, + string customerMembershipName) + { + Assert.Equal(id, actual.Id); + Assert.Equal(name, actual.Name); + Assert.Equal(customerMembershipId, actual.CustomerMembershipId); + Assert.Equal(customerMembershipName, actual.CustomerMembershipName); + } + + AssertSql( + @"SELECT [c].[Id], [c].[Name], [c0].[Id] AS [CustomerMembershipId], CASE WHEN [c0].[Id] IS NOT NULL THEN [c0].[Name] ELSE N'' END AS [CustomerMembershipName] FROM [Customers] AS [c] LEFT JOIN [CustomerMemberships] AS [c0] ON [c].[Id] = [c0].[CustomerId]"); + } } - private SqlServerTestStore CreateDatabase19708() - => CreateTestStore( - () => new BugContext19708(_options), - context => - { - var customer1 = new Customer19708 { Name = "First" }; - var customer2 = new Customer19708 { Name = "Second" }; - var customer3 = new Customer19708 { Name = "Third" }; - - var customerMembership1 = new CustomerMembership19708 { Name = "FirstChild", Customer = customer1 }; - var customerMembership2 = new CustomerMembership19708 { Name = "SecondChild1", Customer = customer2 }; - var customerMembership3 = new CustomerMembership19708 { Name = "SecondChild2", Customer = customer2 }; - - context.AddRange(customer1, customer2, customer3); - context.AddRange(customerMembership1, customerMembership2, customerMembership3); - - context.SaveChanges(); - - ClearLog(); - }); - - private class BugContext19708 : DbContext + protected class IssueContext19708 : DbContext { - public BugContext19708(DbContextOptions options) + public IssueContext19708(DbContextOptions options) : base(options) { } @@ -7007,6 +6355,22 @@ from cm in g.DefaultIfEmpty() #pragma warning restore CS0618 // Type or member is obsolete } + public void Seed() + { + var customer1 = new Customer19708 { Name = "First" }; + var customer2 = new Customer19708 { Name = "Second" }; + var customer3 = new Customer19708 { Name = "Third" }; + + var customerMembership1 = new CustomerMembership19708 { Name = "FirstChild", Customer = customer1 }; + var customerMembership2 = new CustomerMembership19708 { Name = "SecondChild1", Customer = customer2 }; + var customerMembership3 = new CustomerMembership19708 { Name = "SecondChild2", Customer = customer2 }; + + AddRange(customer1, customer2, customer3); + AddRange(customerMembership1, customerMembership2, customerMembership3); + + SaveChanges(); + } + private Expression>> Build_Customers_Sql_View_InMemory() { Expression>> query = () => @@ -7023,35 +6387,35 @@ from customerMembership in nullableCustomerMemberships.DefaultIfEmpty() }; return query; } - } - private class Customer19708 - { - public int Id { get; set; } - public string Name { get; set; } - } + public class Customer19708 + { + public int Id { get; set; } + public string Name { get; set; } + } - private class CustomerMembership19708 - { - public int Id { get; set; } - public string Name { get; set; } + public class CustomerMembership19708 + { + public int Id { get; set; } + public string Name { get; set; } - public int CustomerId { get; set; } - public Customer19708 Customer { get; set; } - } + public int CustomerId { get; set; } + public Customer19708 Customer { get; set; } + } - private class CustomerFilter19708 - { - public int CustomerId { get; set; } - public int CustomerMembershipId { get; set; } - } + public class CustomerFilter19708 + { + public int CustomerId { get; set; } + public int CustomerMembershipId { get; set; } + } - private class CustomerView19708 - { - public int Id { get; set; } - public string Name { get; set; } - public int? CustomerMembershipId { get; set; } - public string CustomerMembershipName { get; set; } + public class CustomerView19708 + { + public int Id { get; set; } + public string Name { get; set; } + public int? CustomerMembershipId { get; set; } + public string CustomerMembershipName { get; set; } + } } #endregion @@ -7059,112 +6423,85 @@ private class CustomerView19708 #region Issue20097 [ConditionalFact] - public void Implicit_interface_casting_though_generic_method() + public async Task Interface_casting_though_generic_method() { - using var _ = CreateDatabase20097(); - using var context = new BugContext20097(_options); + var contextFactory = await InitializeAsync(seed: c => c.Seed()); - var originalQuery = context.Entities.Select(a => new MyModel20097 { Id = a.Id }); - var query = AddFilter(originalQuery, 1).ToList(); + using (var context = contextFactory.CreateContext()) + { + var originalQuery = context.Entities.Select(a => new IssueContext20097.MyModel20097 { Id = a.Id }); + var query = IssueContext20097.AddFilter(originalQuery, 1).ToList(); - Assert.Single(query); + Assert.Single(query); - AssertSql( - @"@__id_0='1' + AssertSql( + @"@__id_0='1' SELECT [e].[Id] FROM [Entities] AS [e] WHERE [e].[Id] = @__id_0"); - } - - [ConditionalFact] - public void Explicit_interface_casting_though_generic_method() - { - using var _ = CreateDatabase20097(); - using var context = new BugContext20097(_options); + ClearLog(); + } - var originalQuery = context.Entities.Select(a => new MyModel20097 { Id = a.Id }); - var query = originalQuery.Where(a => a.Id == 1).ToList(); + using (var context = contextFactory.CreateContext()) + { + var originalQuery = context.Entities.Select(a => new IssueContext20097.MyModel20097 { Id = a.Id }); + var query = originalQuery.Where(a => a.Id == 1).ToList(); - Assert.Single(query); + Assert.Single(query); - AssertSql( - @"SELECT [e].[Id] + AssertSql( + @"SELECT [e].[Id] FROM [Entities] AS [e] WHERE [e].[Id] = CAST(1 AS bigint)"); - } - - [ConditionalFact] - public void Explicit_interface_casting_in_lambda() - { - using var _ = CreateDatabase20097(); - using var context = new BugContext20097(_options); + ClearLog(); + } - var originalQuery = context.Entities.Select(a => new MyModel20097 { Id = a.Id }); - var query = originalQuery.Where(a => ((IHaveId20097)a).Id == 1).ToList(); + using (var context = contextFactory.CreateContext()) + { + var originalQuery = context.Entities.Select(a => new IssueContext20097.MyModel20097 { Id = a.Id }); + var query = originalQuery.Where(a => ((IssueContext20097.IHaveId20097)a).Id == 1).ToList(); - Assert.Single(query); + Assert.Single(query); - AssertSql( - @"SELECT [e].[Id] + AssertSql( + @"SELECT [e].[Id] FROM [Entities] AS [e] WHERE [e].[Id] = CAST(1 AS bigint)"); - } - - [ConditionalFact] - public void Explicit_interface_soft_casting_in_lambda() - { - using var _ = CreateDatabase20097(); - using var context = new BugContext20097(_options); + ClearLog(); + } - var originalQuery = context.Entities.Select(a => new MyModel20097 { Id = a.Id }); - var query = originalQuery.Where(a => (a as IHaveId20097).Id == 1).ToList(); + using (var context = contextFactory.CreateContext()) + { + var originalQuery = context.Entities.Select(a => new IssueContext20097.MyModel20097 { Id = a.Id }); + var query = originalQuery.Where(a => (a as IssueContext20097.IHaveId20097).Id == 1).ToList(); - Assert.Single(query); + Assert.Single(query); - AssertSql( - @"SELECT [e].[Id] + AssertSql( + @"SELECT [e].[Id] FROM [Entities] AS [e] WHERE [e].[Id] = CAST(1 AS bigint)"); - } - - [ConditionalFact] - public void Explicit_interface_casting_checked_in_lambda() - { - using var _ = CreateDatabase20097(); - using var context = new BugContext20097(_options); + ClearLog(); + } - var originalQuery = context.Entities.Select(a => new MyModel20097 { Id = a.Id }); - var query = originalQuery.Where(a => ((IHaveId20097)a).Id == 1).ToList(); - Assert.Single(query); + using (var context = contextFactory.CreateContext()) + { + var originalQuery = context.Entities.Select(a => new IssueContext20097.MyModel20097 { Id = a.Id }); + var query = originalQuery.Where(a => ((IssueContext20097.IHaveId20097)a).Id == 1).ToList(); + Assert.Single(query); - AssertSql( - @"SELECT [e].[Id] + AssertSql( + @"SELECT [e].[Id] FROM [Entities] AS [e] WHERE [e].[Id] = CAST(1 AS bigint)"); + ClearLog(); + } } - private static IQueryable AddFilter(IQueryable query, long id) - where T : IHaveId20097 - { - return query.Where(a => a.Id == id); - } - - private SqlServerTestStore CreateDatabase20097() - => CreateTestStore( - () => new BugContext20097(_options), - context => - { - context.AddRange(new Entity20097()); - - context.SaveChanges(); - - ClearLog(); - }); - - private class BugContext20097 : DbContext + protected class IssueContext20097 : DbContext { - public BugContext20097(DbContextOptions options) + public IssueContext20097(DbContextOptions options) : base(options) { } @@ -7174,77 +6511,53 @@ public BugContext20097(DbContextOptions options) protected override void OnModelCreating(ModelBuilder modelBuilder) { } - } - - private class Entity20097 - { - public long Id { get; set; } - } - - private interface IHaveId20097 - { - long Id { get; } - } - private class MyModel20097 : IHaveId20097 - { - public long Id { get; set; } - } - - #endregion + public static IQueryable AddFilter(IQueryable query, long id) + where T : IHaveId20097 + { + return query.Where(a => a.Id == id); + } - #region Issue20609 + public void Seed() + { + Add(new Entity20097()); - [ConditionalFact] - public virtual void Can_ignore_invalid_include_path_error() - { - using var context = CreateContext20609(); - var result = context.Set().Include("SubB").ToList(); - } + SaveChanges(); + } - private class BaseClass - { - public string Id { get; set; } - } + public class Entity20097 + { + public long Id { get; set; } + } - private class ClassA : BaseClass - { - public SubA SubA { get; set; } - } + public interface IHaveId20097 + { + long Id { get; } + } - private class ClassB : BaseClass - { - public SubB SubB { get; set; } + public class MyModel20097 : IHaveId20097 + { + public long Id { get; set; } + } } - private class SubA - { - public int Id { get; set; } - } + #endregion - private class SubB - { - public int Id { get; set; } - } + #region Issue20609 - private BugContext20609 CreateContext20609() + [ConditionalFact] + public virtual async Task Can_ignore_invalid_include_path_error() { - var testStore = SqlServerTestStore.CreateInitialized("QueryBugsTest", multipleActiveResultSets: true); - var options = Fixture.AddOptions(testStore.AddProviderOptions(new DbContextOptionsBuilder())) - .EnableDetailedErrors() - .EnableServiceProviderCaching(false) - .ConfigureWarnings(x => x.Ignore(CoreEventId.InvalidIncludePathError)) - .Options; + var contextFactory = await InitializeAsync( + onConfiguring: o => o.ConfigureWarnings(x => x.Ignore(CoreEventId.InvalidIncludePathError))); - var context = new BugContext20609(options); - context.Database.EnsureCreatedResiliently(); - - return context; + using var context = contextFactory.CreateContext(); + var result = context.Set().Include("SubB").ToList(); } - private class BugContext20609 : DbContext + protected class IssueContext20609 : DbContext { - public BugContext20609(DbContextOptions options) + public IssueContext20609(DbContextOptions options) : base(options) { } @@ -7258,6 +6571,31 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity().HasBaseType().HasOne(x => x.SubA).WithMany(); modelBuilder.Entity().HasBaseType().HasOne(x => x.SubB).WithMany(); } + + public class BaseClass + { + public string Id { get; set; } + } + + public class ClassA : BaseClass + { + public SubA SubA { get; set; } + } + + public class ClassB : BaseClass + { + public SubB SubB { get; set; } + } + + public class SubA + { + public int Id { get; set; } + } + + public class SubB + { + public int Id { get; set; } + } } #endregion @@ -7265,34 +6603,33 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) #region Issue21355 [ConditionalFact] - public virtual void Can_configure_SingleQuery_at_context_level() + public virtual async Task Can_configure_SingleQuery_at_context_level() { - var (options, testSqlLoggerFactory) = CreateOptions21355(QuerySplittingBehavior.SingleQuery); - using var context = new BugContext21355(options); + var contextFactory = await InitializeAsync(seed: c => c.Seed(), + onConfiguring: o => new SqlServerDbContextOptionsBuilder(o).UseQuerySplittingBehavior(QuerySplittingBehavior.SingleQuery)); - var result = context.Parents.Include(p => p.Children1).ToList(); + using (var context = contextFactory.CreateContext()) + { + var result = context.Parents.Include(p => p.Children1).ToList(); - testSqlLoggerFactory.AssertBaseline( - new[] - { + AssertSql( + new[] + { @"SELECT [p].[Id], [c].[Id], [c].[ParentId] FROM [Parents] AS [p] LEFT JOIN [Child21355] AS [c] ON [p].[Id] = [c].[ParentId] ORDER BY [p].[Id], [c].[Id]" - }); - } - - [ConditionalFact] - public virtual void Can_configure_SplitQuery_at_context_level() - { - var (options, testSqlLoggerFactory) = CreateOptions21355(QuerySplittingBehavior.SplitQuery); - using var context = new BugContext21355(options); + }); + ClearLog(); + } - var result = context.Parents.Include(p => p.Children1).ToList(); + using (var context = contextFactory.CreateContext()) + { + var result = context.Parents.Include(p => p.Children1).AsSplitQuery().ToList(); - testSqlLoggerFactory.AssertBaseline( - new[] - { + AssertSql( + new[] + { @"SELECT [p].[Id] FROM [Parents] AS [p] ORDER BY [p].[Id]", @@ -7301,20 +6638,39 @@ FROM [Parents] AS [p] FROM [Parents] AS [p] INNER JOIN [Child21355] AS [c] ON [p].[Id] = [c].[ParentId] ORDER BY [p].[Id]" - }); + }); + ClearLog(); + } + + using (var context = contextFactory.CreateContext()) + { + context.Parents.Include(p => p.Children1).Include(p => p.Children2).ToList(); + + AssertSql( + new[] + { + @"SELECT [p].[Id], [c].[Id], [c].[ParentId], [a].[Id], [a].[ParentId] +FROM [Parents] AS [p] +LEFT JOIN [Child21355] AS [c] ON [p].[Id] = [c].[ParentId] +LEFT JOIN [AnotherChild21355] AS [a] ON [p].[Id] = [a].[ParentId] +ORDER BY [p].[Id], [c].[Id], [a].[Id]" + }); + } } [ConditionalFact] - public virtual void Can_override_context_level_SingleQuery_with_AsSplitQuery() + public virtual async Task Can_configure_SplitQuery_at_context_level() { - var (options, testSqlLoggerFactory) = CreateOptions21355(QuerySplittingBehavior.SingleQuery); - using var context = new BugContext21355(options); + var contextFactory = await InitializeAsync(seed: c => c.Seed(), + onConfiguring: o => new SqlServerDbContextOptionsBuilder(o).UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery)); - var result = context.Parents.Include(p => p.Children1).AsSplitQuery().ToList(); + using (var context = contextFactory.CreateContext()) + { + var result = context.Parents.Include(p => p.Children1).ToList(); - testSqlLoggerFactory.AssertBaseline( - new[] - { + AssertSql( + new[] + { @"SELECT [p].[Id] FROM [Parents] AS [p] ORDER BY [p].[Id]", @@ -7323,70 +6679,32 @@ FROM [Parents] AS [p] FROM [Parents] AS [p] INNER JOIN [Child21355] AS [c] ON [p].[Id] = [c].[ParentId] ORDER BY [p].[Id]" - }); - } - - [ConditionalFact] - public virtual void Can_override_context_level_SplitQuery_with_AsSingleQuery() - { - var (options, testSqlLoggerFactory) = CreateOptions21355(QuerySplittingBehavior.SplitQuery); - using var context = new BugContext21355(options); + }); + ClearLog(); + } - var result = context.Parents.Include(p => p.Children1).AsSingleQuery().ToList(); + using (var context = contextFactory.CreateContext()) + { + var result = context.Parents.Include(p => p.Children1).AsSingleQuery().ToList(); - testSqlLoggerFactory.AssertBaseline( - new[] - { + AssertSql( + new[] + { @"SELECT [p].[Id], [c].[Id], [c].[ParentId] FROM [Parents] AS [p] LEFT JOIN [Child21355] AS [c] ON [p].[Id] = [c].[ParentId] ORDER BY [p].[Id], [c].[Id]" - }); - } - - [ConditionalFact] - public virtual void Unconfigured_query_splitting_behavior_throws_a_warning() - { - var (options, testSqlLoggerFactory) = CreateOptions21355(null); - using var context = new BugContext21355(options); - - Assert.Contains( - RelationalResources.LogMultipleCollectionIncludeWarning(new TestLogger()) - .GenerateMessage(), - Assert.Throws( - () => context.Parents.Include(p => p.Children1).Include(p => p.Children2).ToList()).Message); - } - - [ConditionalFact] - public virtual void Context_configured_single_query_splitting_behavior_does_not_throw_warning() - { - var (options, testSqlLoggerFactory) = CreateOptions21355(QuerySplittingBehavior.SingleQuery); - using var context = new BugContext21355(options); - - context.Parents.Include(p => p.Children1).Include(p => p.Children2).ToList(); - - testSqlLoggerFactory.AssertBaseline( - new[] - { - @"SELECT [p].[Id], [c].[Id], [c].[ParentId], [a].[Id], [a].[ParentId] -FROM [Parents] AS [p] -LEFT JOIN [Child21355] AS [c] ON [p].[Id] = [c].[ParentId] -LEFT JOIN [AnotherChild21355] AS [a] ON [p].[Id] = [a].[ParentId] -ORDER BY [p].[Id], [c].[Id], [a].[Id]" - }); - } - - [ConditionalFact] - public virtual void Context_configured_split_query_splitting_behavior_does_not_throw_warning() - { - var (options, testSqlLoggerFactory) = CreateOptions21355(QuerySplittingBehavior.SplitQuery); - using var context = new BugContext21355(options); + }); + ClearLog(); + } - context.Parents.Include(p => p.Children1).Include(p => p.Children2).ToList(); + using (var context = contextFactory.CreateContext()) + { + context.Parents.Include(p => p.Children1).Include(p => p.Children2).ToList(); - testSqlLoggerFactory.AssertBaseline( - new[] - { + AssertSql( + new[] + { @"SELECT [p].[Id] FROM [Parents] AS [p] ORDER BY [p].[Id]", @@ -7400,39 +6718,23 @@ FROM [Parents] AS [p] FROM [Parents] AS [p] INNER JOIN [AnotherChild21355] AS [a] ON [p].[Id] = [a].[ParentId] ORDER BY [p].[Id]" - }); - } - - [ConditionalFact] - public virtual void Using_AsSingleQuery_without_context_configuration_does_not_throw_warning() - { - var (options, testSqlLoggerFactory) = CreateOptions21355(null); - using var context = new BugContext21355(options); - - context.Parents.Include(p => p.Children1).Include(p => p.Children2).AsSingleQuery().ToList(); - - testSqlLoggerFactory.AssertBaseline( - new[] - { - @"SELECT [p].[Id], [c].[Id], [c].[ParentId], [a].[Id], [a].[ParentId] -FROM [Parents] AS [p] -LEFT JOIN [Child21355] AS [c] ON [p].[Id] = [c].[ParentId] -LEFT JOIN [AnotherChild21355] AS [a] ON [p].[Id] = [a].[ParentId] -ORDER BY [p].[Id], [c].[Id], [a].[Id]" - }); + }); + } } [ConditionalFact] - public virtual void Using_AsSplitQuery_without_context_configuration_does_not_throw_warning() + public virtual async Task Unconfigured_query_splitting_behavior_throws_a_warning() { - var (options, testSqlLoggerFactory) = CreateOptions21355(null); - using var context = new BugContext21355(options); + var contextFactory = await InitializeAsync( + seed: c => c.Seed(), onConfiguring: o => ClearQuerySplittingBehavior(o)); - context.Parents.Include(p => p.Children1).Include(p => p.Children2).AsSplitQuery().ToList(); + using (var context = contextFactory.CreateContext()) + { + context.Parents.Include(p => p.Children1).Include(p => p.Children2).AsSplitQuery().ToList(); - testSqlLoggerFactory.AssertBaseline( - new[] - { + AssertSql( + new[] + { @"SELECT [p].[Id] FROM [Parents] AS [p] ORDER BY [p].[Id]", @@ -7446,139 +6748,121 @@ FROM [Parents] AS [p] FROM [Parents] AS [p] INNER JOIN [AnotherChild21355] AS [a] ON [p].[Id] = [a].[ParentId] ORDER BY [p].[Id]" - }); - } - - [ConditionalFact] - public virtual void SplitQuery_disposes_inner_data_readers() - { - var (options, testSqlLoggerFactory) = CreateOptions21355(null); - using var context = new BugContext21355(options); - var dbConnection = context.Database.GetDbConnection(); - - Assert.Equal(ConnectionState.Closed, dbConnection.State); - - context.Parents.Include(p => p.Children1).Include(p => p.Children2).AsSplitQuery().ToList(); + }); + } - Assert.Equal(ConnectionState.Closed, dbConnection.State); + using (var context = contextFactory.CreateContext()) + { + Assert.Contains( + RelationalResources.LogMultipleCollectionIncludeWarning(new TestLogger()) + .GenerateMessage(), + Assert.Throws( + () => context.Parents.Include(p => p.Children1).Include(p => p.Children2).ToList()).Message); + } } [ConditionalFact] - public virtual async Task SplitQuery_disposes_inner_data_readers_async() + public virtual async Task Using_AsSingleQuery_without_context_configuration_does_not_throw_warning() { - var (options, testSqlLoggerFactory) = CreateOptions21355(null); - using var context = new BugContext21355(options); - var dbConnection = context.Database.GetDbConnection(); + var contextFactory = await InitializeAsync(seed: c => c.Seed()); - Assert.Equal(ConnectionState.Closed, dbConnection.State); + using var context = contextFactory.CreateContext(); - await context.Parents.Include(p => p.Children1).Include(p => p.Children2).AsSplitQuery().ToListAsync(); + context.Parents.Include(p => p.Children1).Include(p => p.Children2).AsSingleQuery().ToList(); - Assert.Equal(ConnectionState.Closed, dbConnection.State); + AssertSql( + new[] + { + @"SELECT [p].[Id], [c].[Id], [c].[ParentId], [a].[Id], [a].[ParentId] +FROM [Parents] AS [p] +LEFT JOIN [Child21355] AS [c] ON [p].[Id] = [c].[ParentId] +LEFT JOIN [AnotherChild21355] AS [a] ON [p].[Id] = [a].[ParentId] +ORDER BY [p].[Id], [c].[Id], [a].[Id]" + }); } [ConditionalFact] - public virtual void SplitQuery_disposes_inner_data_readers_single() + public virtual async Task SplitQuery_disposes_inner_data_readers() { - var (options, testSqlLoggerFactory) = CreateOptions21355(null); - using var context = new BugContext21355(options); - var dbConnection = context.Database.GetDbConnection(); - - Assert.Equal(ConnectionState.Closed, dbConnection.State); - - context.Parents.Include(p => p.Children1).Include(p => p.Children2).OrderBy(e => e.Id).AsSplitQuery().Single(); + var contextFactory = await InitializeAsync(seed: c => c.Seed()); - Assert.Equal(ConnectionState.Closed, dbConnection.State); - } - - [ConditionalFact] - public virtual async Task SplitQuery_disposes_inner_data_readers_single_async() - { - var (options, testSqlLoggerFactory) = CreateOptions21355(null); - using var context = new BugContext21355(options); - var dbConnection = context.Database.GetDbConnection(); + ((RelationalTestStore)contextFactory.TestStore).CloseConnection(); - Assert.Equal(ConnectionState.Closed, dbConnection.State); + using (var context = contextFactory.CreateContext()) + { + context.Parents.Include(p => p.Children1).Include(p => p.Children2).AsSplitQuery().ToList(); - await context.Parents.Include(p => p.Children1).Include(p => p.Children2).OrderBy(e => e.Id).AsSplitQuery().SingleAsync(); + Assert.Equal(ConnectionState.Closed, context.Database.GetDbConnection().State); + } - Assert.Equal(ConnectionState.Closed, dbConnection.State); - } + using (var context = contextFactory.CreateContext()) + { + await context.Parents.Include(p => p.Children1).Include(p => p.Children2).AsSplitQuery().ToListAsync(); - [ConditionalFact] - public virtual void Using_AsSplitQuery_without_multiple_active_result_sets_work() - { - var (options, testSqlLoggerFactory) = CreateOptions21355(null, mars: true); - using var context = new BugContext21355(options); + Assert.Equal(ConnectionState.Closed, context.Database.GetDbConnection().State); + } - context.Parents.Include(p => p.Children1).Include(p => p.Children2).AsSplitQuery().ToList(); + using (var context = contextFactory.CreateContext()) + { + context.Parents.Include(p => p.Children1).Include(p => p.Children2).OrderBy(e => e.Id).AsSplitQuery().Single(); - var connectionStringWithoutMars = SqlServerTestStore.CreateConnectionString("QueryBugsTest", multipleActiveResultSets: false); - var connection = context.GetService(); - connection.ConnectionString = connectionStringWithoutMars; + Assert.Equal(ConnectionState.Closed, context.Database.GetDbConnection().State); + } - context.Parents.Include(p => p.Children1).Include(p => p.Children2).AsSplitQuery().ToList(); - } + using (var context = contextFactory.CreateContext()) + { + await context.Parents.Include(p => p.Children1).Include(p => p.Children2).OrderBy(e => e.Id).AsSplitQuery().SingleAsync(); - private class Parent21355 - { - public string Id { get; set; } - public List Children1 { get; set; } - public List Children2 { get; set; } + Assert.Equal(ConnectionState.Closed, context.Database.GetDbConnection().State); + } } - private class Child21355 + [ConditionalFact] + public virtual async Task Using_AsSplitQuery_without_multiple_active_result_sets_works() { - public int Id { get; set; } - public string ParentId { get; set; } - public Parent21355 Parent { get; set; } - } + var contextFactory = await InitializeAsync(seed: c => c.Seed(), + createTestStore: () => SqlServerTestStore.CreateInitialized(StoreName, multipleActiveResultSets: false)); - private class AnotherChild21355 - { - public int Id { get; set; } - public string ParentId { get; set; } - public Parent21355 Parent { get; set; } + using var context = contextFactory.CreateContext(); + + context.Parents.Include(p => p.Children1).Include(p => p.Children2).AsSplitQuery().ToList(); } - private (DbContextOptions, TestSqlLoggerFactory) CreateOptions21355( - QuerySplittingBehavior? querySplittingBehavior, - bool mars = true) + protected class IssueContext21355 : DbContext { - var testStore = SqlServerTestStore.CreateInitialized("QueryBugsTest", multipleActiveResultSets: mars); - var testSqlLoggerFactory = new TestSqlLoggerFactory(); - var serviceProvider = new ServiceCollection().AddSingleton(testSqlLoggerFactory).BuildServiceProvider(); + public IssueContext21355(DbContextOptions options) + : base(options) + { + } - var optionsBuilder = Fixture.AddOptions(new DbContextOptionsBuilder().UseSqlServer(testStore.ConnectionString)) - .EnableDetailedErrors() - .EnableServiceProviderCaching(false) - .UseApplicationServiceProvider(serviceProvider); + public DbSet Parents { get; set; } - if (querySplittingBehavior.HasValue) + public void Seed() { - new SqlServerDbContextOptionsBuilder(optionsBuilder).UseQuerySplittingBehavior(querySplittingBehavior.Value); + Add(new Parent21355 { Id = "Parent1", Children1 = new List { new Child21355(), new Child21355() } }); + SaveChanges(); } - var context = new BugContext21355(optionsBuilder.Options); - if (context.Database.EnsureCreatedResiliently()) + public class Parent21355 { - context.Add(new Parent21355 { Id = "Parent1", Children1 = new List { new Child21355(), new Child21355() } }); - context.SaveChanges(); + public string Id { get; set; } + public List Children1 { get; set; } + public List Children2 { get; set; } } - testSqlLoggerFactory.Clear(); - - return (optionsBuilder.Options, testSqlLoggerFactory); - } - - private class BugContext21355 : DbContext - { - public BugContext21355(DbContextOptions options) - : base(options) + public class Child21355 { + public int Id { get; set; } + public string ParentId { get; set; } + public Parent21355 Parent { get; set; } } - public DbSet Parents { get; set; } + public class AnotherChild21355 + { + public int Id { get; set; } + public string ParentId { get; set; } + public Parent21355 Parent { get; set; } + } } #endregion @@ -7586,11 +6870,12 @@ public BugContext21355(DbContextOptions options) #region Issue21540 [ConditionalFact] - public virtual void Can_auto_include_navigation_from_model() + public virtual async Task Can_auto_include_navigation_from_model() { - using (CreateDatabase21540()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext21540(_options); var query = context.Parents.AsNoTracking().ToList(); var result = Assert.Single(query); @@ -7612,15 +6897,11 @@ FROM [JoinEntity21540] AS [j] INNER JOIN [OtherSide21540] AS [o] ON [j].[OtherSideId] = [o].[Id] ) AS [t] ON [p].[Id] = [t].[ParentId] ORDER BY [p].[Id], [r].[Id], [c].[Id], [t].[ParentId], [t].[OtherSideId], [t].[Id]"); + ClearLog(); } - } - [ConditionalFact] - public virtual void Can_ignore_auto_included_navigation_from_model() - { - using (CreateDatabase21540()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext21540(_options); var query = context.Parents.AsNoTracking().IgnoreAutoIncludes().ToList(); var result = Assert.Single(query); @@ -7635,49 +6916,7 @@ public virtual void Can_ignore_auto_included_navigation_from_model() } } - private class Parent21540 - { - public int Id { get; set; } - public Reference21540 Reference { get; set; } - public Owned21540 OwnedReference { get; set; } - public List Collection { get; set; } - public List SkipOtherSide { get; set; } - } - - private class JoinEntity21540 - { - public int ParentId { get; set; } - public Parent21540 Parent { get; set; } - public int OtherSideId { get; set; } - public OtherSide21540 OtherSide { get; set; } - } - - private class OtherSide21540 - { - public int Id { get; set; } - public List SkipParent { get; set; } - } - - private class Reference21540 - { - public int Id { get; set; } - public int ParentId { get; set; } - public Parent21540 Parent { get; set; } - } - - private class Owned21540 - { - public int Id { get; set; } - } - - private class Collection21540 - { - public int Id { get; set; } - public int ParentId { get; set; } - public Parent21540 Parent { get; set; } - } - - private class MyContext21540 : DbContext + protected class MyContext21540 : DbContext { public DbSet Parents { get; set; } @@ -7699,44 +6938,82 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity().Navigation(e => e.Collection).AutoInclude(); modelBuilder.Entity().Navigation(e => e.SkipOtherSide).AutoInclude(); } - } - private SqlServerTestStore CreateDatabase21540() - => CreateTestStore( - () => new MyContext21540(_options), - context => + public void Seed() + { + var joinEntity = new JoinEntity21540 { - var joinEntity = new JoinEntity21540 + OtherSide = new OtherSide21540(), + Parent = new Parent21540 { - OtherSide = new OtherSide21540(), - Parent = new Parent21540 - { - Reference = new Reference21540(), - OwnedReference = new Owned21540(), - Collection = new List + Reference = new Reference21540(), + OwnedReference = new Owned21540(), + Collection = new List { new Collection21540(), new Collection21540(), } - } - }; + } + }; - context.AddRange(joinEntity); + AddRange(joinEntity); - context.SaveChanges(); + SaveChanges(); + } - ClearLog(); - }); + public class Parent21540 + { + public int Id { get; set; } + public Reference21540 Reference { get; set; } + public Owned21540 OwnedReference { get; set; } + public List Collection { get; set; } + public List SkipOtherSide { get; set; } + } + + public class JoinEntity21540 + { + public int ParentId { get; set; } + public Parent21540 Parent { get; set; } + public int OtherSideId { get; set; } + public OtherSide21540 OtherSide { get; set; } + } + + public class OtherSide21540 + { + public int Id { get; set; } + public List SkipParent { get; set; } + } + + public class Reference21540 + { + public int Id { get; set; } + public int ParentId { get; set; } + public Parent21540 Parent { get; set; } + } + + public class Owned21540 + { + public int Id { get; set; } + } + + public class Collection21540 + { + public int Id { get; set; } + public int ParentId { get; set; } + public Parent21540 Parent { get; set; } + } + } #endregion #region Issue18346 [ConditionalFact] - public virtual void Can_query_hierarchy_with_non_nullable_property_on_derived() + public virtual async Task Can_query_hierarchy_with_non_nullable_property_on_derived() { - using (CreateDatabase18346()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext18346(_options); var query = context.Businesses.ToList(); Assert.Equal(3, query.Count); @@ -7746,29 +7023,7 @@ public virtual void Can_query_hierarchy_with_non_nullable_property_on_derived() } } - private abstract class Business18346 - { - public int Id { get; set; } - public string Name { get; set; } - public BusinessType18346 Type { get; set; } - } - - private class Shop18346 : Business18346 - { - public bool IsOnline { get; set; } - } - - private class Brand18346 : Business18346 - { - } - - private enum BusinessType18346 - { - Shop, - Brand, - } - - private class MyContext18346 : DbContext + protected class MyContext18346 : DbContext { public DbSet Businesses { get; set; } @@ -7784,50 +7039,60 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasValue(BusinessType18346.Shop) .HasValue(BusinessType18346.Brand); } - } - private SqlServerTestStore CreateDatabase18346() - => CreateTestStore( - () => new MyContext18346(_options), - context => - { - var shop1 = new Shop18346 { IsOnline = true, Name = "Amzn" }; - var shop2 = new Shop18346 { IsOnline = false, Name = "Mom and Pop's Shoppe" }; - var brand = new Brand18346 { Name = "Tsla" }; - context.Businesses.AddRange(shop1, shop2, brand); - context.SaveChanges(); + public void Seed() + { + var shop1 = new Shop18346 { IsOnline = true, Name = "Amzn" }; + var shop2 = new Shop18346 { IsOnline = false, Name = "Mom and Pop's Shoppe" }; + var brand = new Brand18346 { Name = "Tsla" }; + Businesses.AddRange(shop1, shop2, brand); + SaveChanges(); + } - ClearLog(); - }); + public abstract class Business18346 + { + public int Id { get; set; } + public string Name { get; set; } + public BusinessType18346 Type { get; set; } + } + + public class Shop18346 : Business18346 + { + public bool IsOnline { get; set; } + } + + public class Brand18346 : Business18346 + { + } + + public enum BusinessType18346 + { + Shop, + Brand, + } + } #endregion #region Issue21666 [ConditionalFact] - public virtual void Thread_safety_in_relational_command_cache() + public virtual async Task Thread_safety_in_relational_command_cache() { - using (CreateDatabase21666()) - { - var ids = new[] { 1, 2, 3 }; + var contextFactory = await InitializeAsync(); - Parallel.For( - 0, 100, - i => - { - using var context = new MyContext21666(_options); - var query = context.Lists.Where(l => !l.IsDeleted && ids.Contains(l.Id)).ToList(); - }); - } - } + var ids = new[] { 1, 2, 3 }; - private class List21666 - { - public int Id { get; set; } - public bool IsDeleted { get; set; } + Parallel.For( + 0, 100, + i => + { + using var context = contextFactory.CreateContext(); + var query = context.Lists.Where(l => !l.IsDeleted && ids.Contains(l.Id)).ToList(); + }); } - private class MyContext21666 : DbContext + protected class MyContext21666 : DbContext { public DbSet Lists { get; set; } @@ -7839,35 +7104,35 @@ public MyContext21666(DbContextOptions options) protected override void OnModelCreating(ModelBuilder modelBuilder) { } - } - private SqlServerTestStore CreateDatabase21666() - => CreateTestStore( - () => new MyContext21666(_options), - context => - { - ClearLog(); - }); + public class List21666 + { + public int Id { get; set; } + public bool IsDeleted { get; set; } + } + } #endregion #region Issue21768 [ConditionalFact] - public virtual void Using_explicit_interface_implementation_as_navigation_works() + public virtual async Task Using_explicit_interface_implementation_as_navigation_works() { - using (CreateDatabase21768()) + var contextFactory = await InitializeAsync(); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext21768(_options); - Expression> projection = b => new BookViewModel21768 - { - FirstPage = b.FrontCover.Illustrations.FirstOrDefault(i => i.State >= IllustrationState21768.Approved) != null - ? new PageViewModel21768 + Expression> projection = + b => new MyContext21768.BookViewModel21768 + { + FirstPage = b.FrontCover.Illustrations.FirstOrDefault(i => i.State >= MyContext21768.IllustrationState21768.Approved) != null + ? new MyContext21768.PageViewModel21768 { - Uri = b.FrontCover.Illustrations.FirstOrDefault(i => i.State >= IllustrationState21768.Approved).Uri + Uri = b.FrontCover.Illustrations.FirstOrDefault(i => i.State >= MyContext21768.IllustrationState21768.Approved).Uri } : null, - }; + }; var result = context.Books.Where(b => b.Id == 1).Select(projection).SingleOrDefault(); @@ -7888,137 +7153,129 @@ FROM [Books] AS [b] } } - private class BookViewModel21768 - { - public PageViewModel21768 FirstPage { get; set; } - } - private class PageViewModel21768 + protected class MyContext21768 : DbContext { - public string Uri { get; set; } - } + public DbSet Books { get; set; } + public DbSet BookCovers { get; set; } + public DbSet CoverIllustrations { get; set; } - private interface IBook21768 - { - public int Id { get; set; } + public MyContext21768(DbContextOptions options) + : base(options) + { + } - public IBookCover21768 FrontCover { get; } - public int FrontCoverId { get; set; } + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + foreach (var fk in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys())) + { + fk.DeleteBehavior = DeleteBehavior.NoAction; + } + } - public IBookCover21768 BackCover { get; } - public int BackCoverId { get; set; } - } + public class BookViewModel21768 + { + public PageViewModel21768 FirstPage { get; set; } + } - private interface IBookCover21768 - { - public int Id { get; set; } - public IEnumerable Illustrations { get; } - } + public class PageViewModel21768 + { + public string Uri { get; set; } + } - private interface ICoverIllustration21768 - { - public int Id { get; set; } - public IBookCover21768 Cover { get; } - public int CoverId { get; set; } - public string Uri { get; set; } - public IllustrationState21768 State { get; set; } - } + public interface IBook21768 + { + public int Id { get; set; } - private class Book21768 : IBook21768 - { - public int Id { get; set; } + public IBookCover21768 FrontCover { get; } + public int FrontCoverId { get; set; } - public BookCover21768 FrontCover { get; set; } - public int FrontCoverId { get; set; } + public IBookCover21768 BackCover { get; } + public int BackCoverId { get; set; } + } - public BookCover21768 BackCover { get; set; } - public int BackCoverId { get; set; } + public interface IBookCover21768 + { + public int Id { get; set; } + public IEnumerable Illustrations { get; } + } - IBookCover21768 IBook21768.FrontCover - => FrontCover; + public interface ICoverIllustration21768 + { + public int Id { get; set; } + public IBookCover21768 Cover { get; } + public int CoverId { get; set; } + public string Uri { get; set; } + public IllustrationState21768 State { get; set; } + } - IBookCover21768 IBook21768.BackCover - => BackCover; - } + public class Book21768 : IBook21768 + { + public int Id { get; set; } - private class BookCover21768 : IBookCover21768 - { - public int Id { get; set; } - public ICollection Illustrations { get; set; } + public BookCover21768 FrontCover { get; set; } + public int FrontCoverId { get; set; } - IEnumerable IBookCover21768.Illustrations - => Illustrations; - } + public BookCover21768 BackCover { get; set; } + public int BackCoverId { get; set; } - private class CoverIllustration21768 : ICoverIllustration21768 - { - public int Id { get; set; } - public BookCover21768 Cover { get; set; } - public int CoverId { get; set; } - public string Uri { get; set; } - public IllustrationState21768 State { get; set; } + IBookCover21768 IBook21768.FrontCover + => FrontCover; - IBookCover21768 ICoverIllustration21768.Cover - => Cover; - } + IBookCover21768 IBook21768.BackCover + => BackCover; + } - private enum IllustrationState21768 - { - New, - PendingApproval, - Approved, - Printed - } + public class BookCover21768 : IBookCover21768 + { + public int Id { get; set; } + public ICollection Illustrations { get; set; } - private class MyContext21768 : DbContext - { - public DbSet Books { get; set; } - public DbSet BookCovers { get; set; } - public DbSet CoverIllustrations { get; set; } + IEnumerable IBookCover21768.Illustrations + => Illustrations; + } - public MyContext21768(DbContextOptions options) - : base(options) + public class CoverIllustration21768 : ICoverIllustration21768 { + public int Id { get; set; } + public BookCover21768 Cover { get; set; } + public int CoverId { get; set; } + public string Uri { get; set; } + public IllustrationState21768 State { get; set; } + + IBookCover21768 ICoverIllustration21768.Cover + => Cover; } - protected override void OnModelCreating(ModelBuilder modelBuilder) + public enum IllustrationState21768 { - foreach (var fk in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys())) - { - fk.DeleteBehavior = DeleteBehavior.NoAction; - } + New, + PendingApproval, + Approved, + Printed } } - private SqlServerTestStore CreateDatabase21768() - => CreateTestStore( - () => new MyContext21768(_options), - context => - { - context.SaveChanges(); - - ClearLog(); - }); - #endregion #region Issue19206 [ConditionalFact] - public virtual void From_sql_expression_compares_correctly() + public virtual async Task From_sql_expression_compares_correctly() { - using (CreateDatabase19206()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext19206(_options); - var query = from t1 in context.Tests.FromSqlInterpolated($"Select * from Tests Where Type = {TestType19206.Unit}") - from t2 in context.Tests.FromSqlInterpolated($"Select * from Tests Where Type = {TestType19206.Integration}") + var query = from t1 in context.Tests.FromSqlInterpolated($"Select * from Tests Where Type = {MyContext19206.TestType19206.Unit}") + from t2 in context.Tests.FromSqlInterpolated($"Select * from Tests Where Type = {MyContext19206.TestType19206.Integration}") select new { t1, t2 }; var result = query.ToList(); var item = Assert.Single(result); - Assert.Equal(TestType19206.Unit, item.t1.Type); - Assert.Equal(TestType19206.Integration, item.t2.Type); + Assert.Equal(MyContext19206.TestType19206.Unit, item.t1.Type); + Assert.Equal(MyContext19206.TestType19206.Integration, item.t2.Type); AssertSql( @"p0='0' @@ -8034,19 +7291,7 @@ CROSS JOIN ( } } - private class Test19206 - { - public int Id { get; set; } - public TestType19206 Type { get; set; } - } - - private enum TestType19206 - { - Unit, - Integration, - } - - private class MyContext19206 : DbContext + protected class MyContext19206 : DbContext { public DbSet Tests { get; set; } @@ -8058,30 +7303,39 @@ public MyContext19206(DbContextOptions options) protected override void OnModelCreating(ModelBuilder modelBuilder) { } - } - private SqlServerTestStore CreateDatabase19206() - => CreateTestStore( - () => new MyContext19206(_options), - context => - { - context.Add(new Test19206 { Type = TestType19206.Unit }); - context.Add(new Test19206 { Type = TestType19206.Integration }); - context.SaveChanges(); + public void Seed() + { + Add(new Test19206 { Type = TestType19206.Unit }); + Add(new Test19206 { Type = TestType19206.Integration }); + SaveChanges(); + } - ClearLog(); - }); + public class Test19206 + { + public int Id { get; set; } + public TestType19206 Type { get; set; } + } + + public enum TestType19206 + { + Unit, + Integration, + } + } #endregion #region Issue18510 [ConditionalFact] - public virtual void Invoke_inside_query_filter_gets_correctly_evaluated_during_translation() + public virtual async Task Invoke_inside_query_filter_gets_correctly_evaluated_during_translation() { - using (CreateDatabase18510()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext18510(_options) { TenantId = 1 }; + context.TenantId = 1; var query1 = context.Entities.ToList(); Assert.True(query1.All(x => x.TenantId == 1)); @@ -8105,15 +7359,7 @@ FROM [Entities] AS [e] } } - private class MyEntity18510 - { - public int Id { get; set; } - public string Name { get; set; } - - public int TenantId { get; set; } - } - - private class MyContext18510 : DbContext + protected class MyContext18510 : DbContext { public DbSet Entities { get; set; } @@ -8147,23 +7393,26 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) entityType.SetQueryFilter(updatedQueryFilter); } - } - private SqlServerTestStore CreateDatabase18510() - => CreateTestStore( - () => new MyContext18510(_options), - context => - { - var e1 = new MyEntity18510 { Name = "e1", TenantId = 1 }; - var e2 = new MyEntity18510 { Name = "e2", TenantId = 2 }; - var e3 = new MyEntity18510 { Name = "e3", TenantId = 2 }; - var e4 = new MyEntity18510 { Name = "Foo", TenantId = 2 }; + public void Seed() + { + var e1 = new MyEntity18510 { Name = "e1", TenantId = 1 }; + var e2 = new MyEntity18510 { Name = "e2", TenantId = 2 }; + var e3 = new MyEntity18510 { Name = "e3", TenantId = 2 }; + var e4 = new MyEntity18510 { Name = "Foo", TenantId = 2 }; - context.Entities.AddRange(e1, e2, e3, e4); - context.SaveChanges(); + Entities.AddRange(e1, e2, e3, e4); + SaveChanges(); + } - ClearLog(); - }); + public class MyEntity18510 + { + public int Id { get; set; } + public string Name { get; set; } + + public int TenantId { get; set; } + } + } #endregion @@ -8176,11 +7425,11 @@ private SqlServerTestStore CreateDatabase18510() [InlineData(false, false)] public virtual async Task Select_enumerable_navigation_backed_by_collection(bool async, bool split) { - using (CreateDatabase21803()) - { - using var context = new MyContext21803(_options); + var contextFactory = await InitializeAsync(seed: c => c.Seed()); - var query = context.Set().Select(appEntity => appEntity.OtherEntities); + using (var context = contextFactory.CreateContext()) + { + var query = context.Set().Select(appEntity => appEntity.OtherEntities); if (split) { @@ -8219,23 +7468,7 @@ FROM [Entities] AS [e] } } - private class AppEntity21803 - { - private readonly List _otherEntities = new List(); - - public int Id { get; private set; } - - public IEnumerable OtherEntities - => _otherEntities; - } - - private class OtherEntity21803 - { - public int Id { get; private set; } - public AppEntity21803 AppEntity { get; set; } - } - - private class MyContext21803 : DbContext + protected class MyContext21803 : DbContext { public DbSet Entities { get; set; } @@ -8243,37 +7476,48 @@ public MyContext21803(DbContextOptions options) : base(options) { } - } - private SqlServerTestStore CreateDatabase21803() - => CreateTestStore( - () => new MyContext21803(_options), - context => - { - var appEntity = new AppEntity21803(); - context.AddRange( - new OtherEntity21803 { AppEntity = appEntity }, - new OtherEntity21803 { AppEntity = appEntity }, - new OtherEntity21803 { AppEntity = appEntity }, - new OtherEntity21803 { AppEntity = appEntity }); + public void Seed() + { + var appEntity = new AppEntity21803(); + AddRange( + new OtherEntity21803 { AppEntity = appEntity }, + new OtherEntity21803 { AppEntity = appEntity }, + new OtherEntity21803 { AppEntity = appEntity }, + new OtherEntity21803 { AppEntity = appEntity }); - context.SaveChanges(); + SaveChanges(); + } - ClearLog(); - }); + public class AppEntity21803 + { + private readonly List _otherEntities = new List(); + + public int Id { get; private set; } + + public IEnumerable OtherEntities + => _otherEntities; + } + + public class OtherEntity21803 + { + public int Id { get; private set; } + public AppEntity21803 AppEntity { get; set; } + } + } #endregion #region Issue21807 [ConditionalFact] - public virtual void Nested_owned_required_dependents_are_materialized() + public virtual async Task Nested_owned_required_dependents_are_materialized() { - using (CreateDatabase21807()) - { - using var context = new MyContext21807(_options); + var contextFactory = await InitializeAsync(seed: c => c.Seed()); - var query = context.Set().ToList(); + using (var context = contextFactory.CreateContext()) + { + var query = context.Set().ToList(); var result = Assert.Single(query); Assert.NotNull(result.Contact); @@ -8286,27 +7530,7 @@ public virtual void Nested_owned_required_dependents_are_materialized() } } - private class Entity21807 - { - public string Id { get; set; } - public Contact21807 Contact { get; set; } - } - - private class Contact21807 - { - public string Name { get; set; } - public Address21807 Address { get; set; } - } - - private class Address21807 - { - public string Street { get; set; } - public string City { get; set; } - public string State { get; set; } - public string Zip { get; set; } - } - - private class MyContext21807 : DbContext + protected class MyContext21807 : DbContext { public MyContext21807(DbContextOptions options) : base(options) @@ -8329,32 +7553,47 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) builder.Navigation(x => x.Contact).IsRequired(); }); } - } - private SqlServerTestStore CreateDatabase21807() - => CreateTestStore( - () => new MyContext21807(_options), - context => - { - context.Add(new Entity21807 { Id = "1", Contact = new Contact21807 { Address = new Address21807 { Zip = "12345" } } }); + public void Seed() + { + Add(new Entity21807 { Id = "1", Contact = new Contact21807 { Address = new Address21807 { Zip = "12345" } } }); - context.SaveChanges(); + SaveChanges(); + } - ClearLog(); - }); + public class Entity21807 + { + public string Id { get; set; } + public Contact21807 Contact { get; set; } + } + + public class Contact21807 + { + public string Name { get; set; } + public Address21807 Address { get; set; } + } + + public class Address21807 + { + public string Street { get; set; } + public string City { get; set; } + public string State { get; set; } + public string Zip { get; set; } + } + } #endregion #region Issue22054 [ConditionalFact] - public virtual void Optional_dependent_is_null_when_sharing_required_column_with_principal() + public virtual async Task Optional_dependent_is_null_when_sharing_required_column_with_principal() { - using (CreateDatabase22054()) - { - using var context = new MyContext22054(_options); + var contextFactory = await InitializeAsync(seed: c => c.Seed()); - var query = context.Set().OrderByDescending(e => e.Id).ToList(); + using (var context = contextFactory.CreateContext()) + { + var query = context.Set().OrderByDescending(e => e.Id).ToList(); Assert.Equal(3, query.Count); @@ -8374,34 +7613,7 @@ FROM [User22054] AS [u] } } - private class User22054 - { - public int Id { get; set; } - public Data22054 Data { get; set; } - public Contact22054 Contact { get; set; } - public byte[] RowVersion { get; set; } - } - - private class Data22054 - { - public string Data { get; set; } - } - - private class Contact22054 - { - public string MobileNumber { get; set; } - public string SharedProperty { get; set; } - public Address22054 Address { get; set; } - } - - private class Address22054 - { - public string City { get; set; } - public string SharedProperty { get; set; } - public string Zip { get; set; } - } - - private class MyContext22054 : DbContext + protected class MyContext22054 : DbContext { public MyContext22054(DbContextOptions options) : base(options) @@ -8441,14 +7653,10 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasColumnName("RowVersion"); }); } - } - private SqlServerTestStore CreateDatabase22054() - => CreateTestStore( - () => new MyContext22054(_options), - context => - { - context.AddRange( + public void Seed() + { + AddRange( new User22054 { Data = new Data22054 { Data = "Data1" }, @@ -8476,23 +7684,49 @@ private SqlServerTestStore CreateDatabase22054() }, new User22054 { Contact = null, Data = null }); - context.SaveChanges(); + SaveChanges(); + } - ClearLog(); - }); + public class User22054 + { + public int Id { get; set; } + public Data22054 Data { get; set; } + public Contact22054 Contact { get; set; } + public byte[] RowVersion { get; set; } + } + + public class Data22054 + { + public string Data { get; set; } + } + + public class Contact22054 + { + public string MobileNumber { get; set; } + public string SharedProperty { get; set; } + public Address22054 Address { get; set; } + } + + public class Address22054 + { + public string City { get; set; } + public string SharedProperty { get; set; } + public string Zip { get; set; } + } + } #endregion #region Issue14911 [ConditionalFact] - public virtual void Owned_entity_multiple_level_in_aggregate() + public virtual async Task Owned_entity_multiple_level_in_aggregate() { - using (CreateDatabase14911()) - { - using var context = new MyContext14911(_options); + var contextFactory = await InitializeAsync(seed: c => c.Seed()); - var aggregate = context.Set().OrderByDescending(e => e.Id).FirstOrDefault(); + using (var context = contextFactory.CreateContext()) + { + var aggregate = context.Set().OrderByDescending(e => e.Id).FirstOrDefault(); Assert.Equal(10, aggregate.FirstValueObject.SecondValueObjects[0].FourthValueObject.FifthValueObjects[0].AnyValue); Assert.Equal(20, aggregate.FirstValueObject.SecondValueObjects[0].ThirdValueObjects[0].FourthValueObject.FifthValueObjects[0].AnyValue); @@ -8518,39 +7752,7 @@ FROM [ThirdValueObjects] AS [t0] } } - private class Aggregate14911 - { - public int Id { get; set; } - public FirstValueObject14911 FirstValueObject { get; set; } - } - - private class FirstValueObject14911 - { - public List SecondValueObjects { get; set; } - } - - private class SecondValueObject14911 - { - public FourthValueObject14911 FourthValueObject { get; set; } - public List ThirdValueObjects { get; set; } - } - - private class ThirdValueObject14911 - { - public FourthValueObject14911 FourthValueObject { get; set; } - } - - private class FourthValueObject14911 - { - public List FifthValueObjects { get; set; } - } - - private class FifthValueObject14911 - { - public int AnyValue { get; set; } - } - - private class MyContext14911 : DbContext + protected class MyContext14911 : DbContext { public MyContext14911(DbContextOptions options) : base(options) @@ -8606,18 +7808,14 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) }); }); } - } - private SqlServerTestStore CreateDatabase14911() - => CreateTestStore( - () => new MyContext14911(_options), - context => + public void Seed() + { + var aggregate = new Aggregate14911 { - var aggregate = new Aggregate14911 + FirstValueObject = new FirstValueObject14911 { - FirstValueObject = new FirstValueObject14911 - { - SecondValueObjects = new List + SecondValueObjects = new List { new SecondValueObject14911 { @@ -8643,27 +7841,58 @@ private SqlServerTestStore CreateDatabase14911() } } } - } - }; + } + }; - context.Set().Add(aggregate); + Set().Add(aggregate); - context.SaveChanges(); + SaveChanges(); + } - ClearLog(); - }); + public class Aggregate14911 + { + public int Id { get; set; } + public FirstValueObject14911 FirstValueObject { get; set; } + } + + public class FirstValueObject14911 + { + public List SecondValueObjects { get; set; } + } + + public class SecondValueObject14911 + { + public FourthValueObject14911 FourthValueObject { get; set; } + public List ThirdValueObjects { get; set; } + } + + public class ThirdValueObject14911 + { + public FourthValueObject14911 FourthValueObject { get; set; } + } + + public class FourthValueObject14911 + { + public List FifthValueObjects { get; set; } + } + + public class FifthValueObject14911 + { + public int AnyValue { get; set; } + } + } #endregion #region Issue15215 [ConditionalFact] - public virtual void Repeated_parameters_in_generated_query_sql() + public virtual async Task Repeated_parameters_in_generated_query_sql() { - using (CreateDatabase15215()) - { - using var context = new MyContext15215(_options); + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + using (var context = contextFactory.CreateContext()) + { var k = 1; var a = context.Autos.Where(e => e.Id == k).First(); var b = context.Autos.Where(e => e.Id == k + 1).First(); @@ -8699,21 +7928,7 @@ FROM [EqualAutos] AS [e] } } - private class Auto15215 - { - public int Id { get; set; } - public string Name { get; set; } - } - - private class EqualAuto15215 - { - public int Id { get; set; } - public Auto15215 Auto { get; set; } - public Auto15215 AnotherAuto { get; set; } - } - - - private class MyContext15215 : DbContext + protected class MyContext15215 : DbContext { public MyContext15215(DbContextOptions options) : base(options) @@ -8722,48 +7937,56 @@ public MyContext15215(DbContextOptions options) public DbSet Autos { get; set; } public DbSet EqualAutos { get; set; } - } - private SqlServerTestStore CreateDatabase15215() - => CreateTestStore( - () => new MyContext15215(_options), - context => + public void Seed() + { + for (var i = 0; i < 10; i++) { - for (var i = 0; i < 10; i++) - { - context.Add(new Auto15215 { Name = "Auto " + i.ToString() }); - } + Add(new Auto15215 { Name = "Auto " + i.ToString() }); + } - context.SaveChanges(); + SaveChanges(); - context.AddRange( - new EqualAuto15215 - { - Auto = context.Autos.Find(1), - AnotherAuto = context.Autos.Find(2) - }, - new EqualAuto15215 - { - Auto = context.Autos.Find(5), - AnotherAuto = context.Autos.Find(4) - }); + AddRange( + new EqualAuto15215 + { + Auto = Autos.Find(1), + AnotherAuto = Autos.Find(2) + }, + new EqualAuto15215 + { + Auto = Autos.Find(5), + AnotherAuto = Autos.Find(4) + }); - context.SaveChanges(); + SaveChanges(); + } - ClearLog(); - }); + public class Auto15215 + { + public int Id { get; set; } + public string Name { get; set; } + } + + public class EqualAuto15215 + { + public int Id { get; set; } + public Auto15215 Auto { get; set; } + public Auto15215 AnotherAuto { get; set; } + } + } #endregion #region Issue22340 [ConditionalFact] - public virtual void Owned_entity_mapped_to_separate_table() + public virtual async Task Owned_entity_mapped_to_separate_table() { - using (CreateDatabase22340()) - { - using var context = new MyContext22340(_options); + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + using (var context = contextFactory.CreateContext()) + { var masterTrunk = context.MasterTrunk.OrderBy(e => EF.Property(e, "Id")).FirstOrDefault(); //exception Sequence contains no elements. Assert.NotNull(masterTrunk); @@ -8783,26 +8006,7 @@ ORDER BY [m].[Id] } } - private class MasterTrunk22340 - { - public CurrencyBag22340 FungibleBag { get; set; } - public CurrencyBag22340 StaticBag { get; set; } - } - - private class CurrencyBag22340 - { - public IEnumerable Currencies { get; set; } - } - - private class Currency22340 - { - [Column(TypeName = "decimal(18,2)")] - public decimal Amount { get; set; } - [Column(TypeName = "decimal(18,2)")] - public decimal Code { get; set; } - } - - private class MyContext22340 : DbContext + protected class MyContext22340 : DbContext { public MyContext22340(DbContextOptions options) : base(options) @@ -8837,64 +8041,78 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) p.ToTable("StaticBag"); }); } - } - private SqlServerTestStore CreateDatabase22340() - => CreateTestStore( - () => new MyContext22340(_options), - context => + public void Seed() + { + var masterTrunk = new MasterTrunk22340() { - var masterTrunk = new MasterTrunk22340() + FungibleBag = new CurrencyBag22340() { - FungibleBag = new CurrencyBag22340() + Currencies = new Currency22340[] { - Currencies = new Currency22340[] - { new Currency22340() { Amount = 10, Code = 999 } - } - }, - StaticBag = new CurrencyBag22340() + } + }, + StaticBag = new CurrencyBag22340() + { + Currencies = new Currency22340[] { - Currencies = new Currency22340[] - { new Currency22340() { Amount = 555, Code = 111 } - } } - }; - context.Add(masterTrunk); + } + }; + Add(masterTrunk); + + SaveChanges(); + } - context.SaveChanges(); + public class MasterTrunk22340 + { + public CurrencyBag22340 FungibleBag { get; set; } + public CurrencyBag22340 StaticBag { get; set; } + } - ClearLog(); - }); + public class CurrencyBag22340 + { + public IEnumerable Currencies { get; set; } + } + + public class Currency22340 + { + [Column(TypeName = "decimal(18,2)")] + public decimal Amount { get; set; } + [Column(TypeName = "decimal(18,2)")] + public decimal Code { get; set; } + } + } #endregion #region Issue22568 [ConditionalFact] - public virtual void Cycles_in_auto_include_one_to_one() + public virtual async Task Cycles_in_auto_include() { - using (CreateDatabase22568()) - { - using var context = new MyContext22568(_options); + var contextFactory = await InitializeAsync(seed: c => c.Seed()); - var principals = context.Set().ToList(); + using (var context = contextFactory.CreateContext()) + { + var principals = context.Set().ToList(); Assert.Single(principals); Assert.NotNull(principals[0].Dependent); Assert.NotNull(principals[0].Dependent.Principal); - var dependents = context.Set().ToList(); + var dependents = context.Set().ToList(); Assert.Single(dependents); Assert.NotNull(dependents[0].Principal); Assert.NotNull(dependents[0].Principal.Dependent); @@ -8907,22 +8125,17 @@ FROM [PrincipalOneToOne] AS [p] @"SELECT [d].[Id], [d].[PrincipalId], [p].[Id] FROM [DependentOneToOne] AS [d] INNER JOIN [PrincipalOneToOne] AS [p] ON [d].[PrincipalId] = [p].[Id]"); + ClearLog(); } - } - [ConditionalFact] - public virtual void Cycles_in_auto_include_one_to_many() - { - using (CreateDatabase22568()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext22568(_options); - - var principals = context.Set().ToList(); + var principals = context.Set().ToList(); Assert.Single(principals); Assert.NotNull(principals[0].Dependents); Assert.True(principals[0].Dependents.All(e => e.Principal != null)); - var dependents = context.Set().ToList(); + var dependents = context.Set().ToList(); Assert.Equal(2, dependents.Count); Assert.True(dependents.All(e => e.Principal != null)); Assert.True(dependents.All(e => e.Principal.Dependents != null)); @@ -8939,26 +8152,21 @@ FROM [DependentOneToMany] AS [d] INNER JOIN [PrincipalOneToMany] AS [p] ON [d].[PrincipalId] = [p].[Id] LEFT JOIN [DependentOneToMany] AS [d0] ON [p].[Id] = [d0].[PrincipalId] ORDER BY [d].[Id], [p].[Id], [d0].[Id]"); + ClearLog(); } - } - [ConditionalFact] - public virtual void Cycles_in_auto_include_many_to_many_throws() - { - using (CreateDatabase22568()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext22568(_options); - Assert.Equal( CoreStrings.AutoIncludeNavigationCycle("'PrincipalManyToMany.Dependents', 'DependentManyToMany.Principals'"), - Assert.Throws(() => context.Set().ToList()).Message); + Assert.Throws(() => context.Set().ToList()).Message); Assert.Equal( CoreStrings.AutoIncludeNavigationCycle("'DependentManyToMany.Principals', 'PrincipalManyToMany.Dependents'"), - Assert.Throws(() => context.Set().ToList()).Message); + Assert.Throws(() => context.Set().ToList()).Message); - context.Set().IgnoreAutoIncludes().ToList(); - context.Set().IgnoreAutoIncludes().ToList(); + context.Set().IgnoreAutoIncludes().ToList(); + context.Set().IgnoreAutoIncludes().ToList(); AssertSql( @"SELECT [p].[Id] @@ -8966,31 +8174,26 @@ public virtual void Cycles_in_auto_include_many_to_many_throws() // @"SELECT [d].[Id] FROM [DependentManyToMany] AS [d]"); + ClearLog(); } - } - [ConditionalFact] - public virtual void Cycles_in_auto_include_multi_level_throws() - { - using (CreateDatabase22568()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext22568(_options); - Assert.Equal( CoreStrings.AutoIncludeNavigationCycle("'CycleA.Bs', 'CycleB.C', 'CycleC.As'"), - Assert.Throws(() => context.Set().ToList()).Message); + Assert.Throws(() => context.Set().ToList()).Message); Assert.Equal( CoreStrings.AutoIncludeNavigationCycle("'CycleB.C', 'CycleC.As', 'CycleA.Bs'"), - Assert.Throws(() => context.Set().ToList()).Message); + Assert.Throws(() => context.Set().ToList()).Message); Assert.Equal( CoreStrings.AutoIncludeNavigationCycle("'CycleC.As', 'CycleA.Bs', 'CycleB.C'"), - Assert.Throws(() => context.Set().ToList()).Message); + Assert.Throws(() => context.Set().ToList()).Message); - context.Set().IgnoreAutoIncludes().ToList(); - context.Set().IgnoreAutoIncludes().ToList(); - context.Set().IgnoreAutoIncludes().ToList(); + context.Set().IgnoreAutoIncludes().ToList(); + context.Set().IgnoreAutoIncludes().ToList(); + context.Set().IgnoreAutoIncludes().ToList(); AssertSql( @"SELECT [c].[Id], [c].[CycleCId] @@ -9004,68 +8207,7 @@ public virtual void Cycles_in_auto_include_multi_level_throws() } } - private class PrincipalOneToOne - { - public int Id { get; set; } - public DependentOneToOne Dependent { get; set; } - } - - private class DependentOneToOne - { - public int Id { get; set; } - [ForeignKey("Principal")] - public int PrincipalId { get; set; } - public PrincipalOneToOne Principal { get; set; } - } - - private class PrincipalOneToMany - { - public int Id { get; set; } - public List Dependents { get; set; } - } - - private class DependentOneToMany - { - public int Id { get; set; } - [ForeignKey("Principal")] - public int PrincipalId { get; set; } - public PrincipalOneToMany Principal { get; set; } - } - - private class PrincipalManyToMany - { - public int Id { get; set; } - public List Dependents { get; set; } - } - - private class DependentManyToMany - { - public int Id { get; set; } - public List Principals { get; set; } - } - - private class CycleA - { - public int Id { get; set; } - public List Bs { get; set; } - } - - private class CycleB - { - public int Id { get; set; } - public CycleC C { get; set; } - } - - private class CycleC - { - public int Id { get; set; } - [ForeignKey("B")] - public int BId { get; set; } - private CycleB B { get; set; } - public List As { get; set; } - } - - private class MyContext22568 : DbContext + protected class MyContext22568 : DbContext { public MyContext22568(DbContextOptions options) : base(options) @@ -9085,39 +8227,97 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity().Navigation(e => e.C).AutoInclude(); modelBuilder.Entity().Navigation(e => e.As).AutoInclude(); } - } - private SqlServerTestStore CreateDatabase22568() - => CreateTestStore( - () => new MyContext22568(_options), - context => + public void Seed() + { + Add(new PrincipalOneToOne { Dependent = new DependentOneToOne() }); + Add(new PrincipalOneToMany { - context.Add(new PrincipalOneToOne { Dependent = new DependentOneToOne() }); - context.Add(new PrincipalOneToMany - { - Dependents = new List + Dependents = new List { new DependentOneToMany(), new DependentOneToMany(), } - }); + }); + + SaveChanges(); + } + + public class PrincipalOneToOne + { + public int Id { get; set; } + public DependentOneToOne Dependent { get; set; } + } + + public class DependentOneToOne + { + public int Id { get; set; } + [ForeignKey("Principal")] + public int PrincipalId { get; set; } + public PrincipalOneToOne Principal { get; set; } + } + + public class PrincipalOneToMany + { + public int Id { get; set; } + public List Dependents { get; set; } + } + + public class DependentOneToMany + { + public int Id { get; set; } + [ForeignKey("Principal")] + public int PrincipalId { get; set; } + public PrincipalOneToMany Principal { get; set; } + } + + public class PrincipalManyToMany + { + public int Id { get; set; } + public List Dependents { get; set; } + } + + public class DependentManyToMany + { + public int Id { get; set; } + public List Principals { get; set; } + } + + public class CycleA + { + public int Id { get; set; } + public List Bs { get; set; } + } - context.SaveChanges(); + public class CycleB + { + public int Id { get; set; } + public CycleC C { get; set; } + } - ClearLog(); - }); + public class CycleC + { + public int Id { get; set; } + [ForeignKey("B")] + public int BId { get; set; } + private CycleB B { get; set; } + public List As { get; set; } + } + } #endregion #region Issue12274 [ConditionalFact] - public virtual void Parameterless_ctor_on_inner_DTO_gets_called_for_every_row() + public virtual async Task Parameterless_ctor_on_inner_DTO_gets_called_for_every_row() { - using (CreateDatabase12274()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext12274(_options); - var results = context.Entities.Select(x => new OuterDTO12274 { Id = x.Id, Name = x.Name, Inner = new InnerDTO12274() }).ToList(); + var results = context.Entities.Select(x => + new MyContext12274.OuterDTO12274 { Id = x.Id, Name = x.Name, Inner = new MyContext12274.InnerDTO12274() }).ToList(); Assert.Equal(4, results.Count); Assert.False(ReferenceEquals(results[0].Inner, results[1].Inner)); Assert.False(ReferenceEquals(results[1].Inner, results[2].Inner)); @@ -9125,7 +8325,7 @@ public virtual void Parameterless_ctor_on_inner_DTO_gets_called_for_every_row() } } - private class MyContext12274 : DbContext + protected class MyContext12274 : DbContext { public DbSet Entities { get; set; } @@ -9133,53 +8333,50 @@ public MyContext12274(DbContextOptions options) : base(options) { } - } - public class MyEntity12274 - { - public int Id { get; set; } - public string Name { get; set; } - } + public void Seed() + { + var e1 = new MyEntity12274 { Name = "1" }; + var e2 = new MyEntity12274 { Name = "2" }; + var e3 = new MyEntity12274 { Name = "3" }; + var e4 = new MyEntity12274 { Name = "4" }; - public class OuterDTO12274 - { - public int Id { get; set; } - public string Name { get; set; } - public InnerDTO12274 Inner { get; set; } - } + Entities.AddRange(e1, e2, e3, e4); + SaveChanges(); + } - public class InnerDTO12274 - { - public InnerDTO12274() + public class MyEntity12274 + { + public int Id { get; set; } + public string Name { get; set; } + } + + public class OuterDTO12274 { + public int Id { get; set; } + public string Name { get; set; } + public InnerDTO12274 Inner { get; set; } } - } - private SqlServerTestStore CreateDatabase12274() - => CreateTestStore( - () => new MyContext12274(_options), - context => + public class InnerDTO12274 + { + public InnerDTO12274() { - var e1 = new MyEntity12274 { Name = "1" }; - var e2 = new MyEntity12274 { Name = "2" }; - var e3 = new MyEntity12274 { Name = "3" }; - var e4 = new MyEntity12274 { Name = "4" }; - - context.Entities.AddRange(e1, e2, e3, e4); - context.SaveChanges(); - ClearLog(); - }); + } + } + } #endregion #region Issue11835 [ConditionalFact] - public virtual void Projecting_correlated_collection_along_with_non_mapped_property() + public virtual async Task Projecting_correlated_collection_along_with_non_mapped_property() { - using (CreateDatabase11835()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext11835(_options); var result = context.Blogs.Select( e => new { @@ -9197,15 +8394,11 @@ FROM [Posts] AS [p] WHERE [p].[Name] LIKE N'%2%' ) AS [t] ON [b].[Id] = [t].[BlogId] ORDER BY [b].[Id], [t].[Id]"); + ClearLog(); } - } - [ConditionalFact] - public virtual void Projecting_element_from_correlated_collection_along_with_non_mapped_property() - { - using (CreateDatabase11835()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext11835(_options); var result = context.Blogs.Select( e => new { @@ -9224,7 +8417,7 @@ FROM [Posts] AS [p] } } - private class MyContext11835 : DbContext + protected class MyContext11835 : DbContext { public DbSet Blogs { get; set; } public DbSet Posts { get; set; } @@ -9233,55 +8426,51 @@ public MyContext11835(DbContextOptions options) : base(options) { } - } - public class Blog11835 - { - public int Id { get; set; } - [NotMapped] - public string Title { get; set; } - public List Posts { get; set; } - } - public class Post11835 - { - public int Id { get; set; } - public int BlogId { get; set; } - public Blog11835 Blog { get; set; } - public string Name { get; set; } - } + public void Seed() + { + var b1 = new Blog11835 { Title = "B1" }; + var b2 = new Blog11835 { Title = "B2" }; + var p11 = new Post11835 { Name = "P11", Blog = b1 }; + var p12 = new Post11835 { Name = "P12", Blog = b1 }; + var p13 = new Post11835 { Name = "P13", Blog = b1 }; + var p21 = new Post11835 { Name = "P21", Blog = b2 }; + var p22 = new Post11835 { Name = "P22", Blog = b2 }; - private SqlServerTestStore CreateDatabase11835() - => CreateTestStore( - () => new MyContext11835(_options), - context => - { - var b1 = new Blog11835 { Title = "B1" }; - var b2 = new Blog11835 { Title = "B2" }; - var p11 = new Post11835 { Name = "P11", Blog = b1 }; - var p12 = new Post11835 { Name = "P12", Blog = b1 }; - var p13 = new Post11835 { Name = "P13", Blog = b1 }; - var p21 = new Post11835 { Name = "P21", Blog = b2 }; - var p22 = new Post11835 { Name = "P22", Blog = b2 }; - - context.Blogs.AddRange(b1, b2); - context.Posts.AddRange(p11, p12, p13, p21, p22); - context.SaveChanges(); - - ClearLog(); - }); + Blogs.AddRange(b1, b2); + Posts.AddRange(p11, p12, p13, p21, p22); + SaveChanges(); + } + + public class Blog11835 + { + public int Id { get; set; } + [NotMapped] + public string Title { get; set; } + public List Posts { get; set; } + } + + public class Post11835 + { + public int Id { get; set; } + public int BlogId { get; set; } + public Blog11835 Blog { get; set; } + public string Name { get; set; } + } + } #endregion #region Issue23211 [ConditionalFact] - public virtual void Collection_include_on_owner_with_two_owned_types_mapped_to_different_table() + public virtual async Task Collection_include_on_owner_with_owned_type_mapped_to_different_table() { - using (CreateDatabase23211()) - { - using var context = new MyContext23211(_options); + var contextFactory = await InitializeAsync(seed: c => c.Seed()); - var owner = context.Set().Include(e => e.Dependents).AsSplitQuery().OrderBy(e => e.Id).Single(); + using (var context = contextFactory.CreateContext()) + { + var owner = context.Set().Include(e => e.Dependents).AsSplitQuery().OrderBy(e => e.Id).Single(); Assert.NotNull(owner.Dependents); Assert.Equal(2, owner.Dependents.Count); Assert.NotNull(owner.Owned1); @@ -9308,17 +8497,12 @@ ORDER BY [o].[Id] ) AS [t] INNER JOIN [Dependent23211] AS [d] ON [t].[Id] = [d].[Owner23211Id] ORDER BY [t].[Id]"); + ClearLog(); } - } - [ConditionalFact] - public virtual void Collection_include_on_owner_with_owned_type_mapped_to_different_table() - { - using (CreateDatabase23211()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext23211(_options); - - var owner = context.Set().Include(e => e.Dependents).AsSplitQuery().OrderBy(e => e.Id).Single(); + var owner = context.Set().Include(e => e.Dependents).AsSplitQuery().OrderBy(e => e.Id).Single(); Assert.NotNull(owner.Dependents); Assert.Equal(2, owner.Dependents.Count); Assert.NotNull(owner.Owned); @@ -9345,37 +8529,7 @@ ORDER BY [s].[Id] } } - private class Owner23211 - { - public int Id { get; set; } - public List Dependents { get; set; } - public OwnedType23211 Owned1 { get; set; } - public OwnedType23211 Owned2 { get; set; } - } - - private class OwnedType23211 - { - public string Value { get; set; } - } - - private class Dependent23211 - { - public int Id { get; set; } - } - - private class SecondOwner23211 - { - public int Id { get; set; } - public List Dependents { get; set; } - public OwnedType23211 Owned { get; set; } - } - - private class SecondDependent23211 - { - public int Id { get; set; } - } - - private class MyContext23211 : DbContext + protected class MyContext23211 : DbContext { public MyContext23211(DbContextOptions options) : base(options) @@ -9388,49 +8542,75 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity().OwnsOne(e => e.Owned2, b => b.ToTable("Owned223211")); modelBuilder.Entity().OwnsOne(e => e.Owned, b => b.ToTable("Owned23211")); } - } - private SqlServerTestStore CreateDatabase23211() - => CreateTestStore( - () => new MyContext23211(_options), - context => + public void Seed() + { + Add(new Owner23211 { - context.Add(new Owner23211 - { - Dependents = new List + Dependents = new List { new Dependent23211(), new Dependent23211() }, - Owned1 = new OwnedType23211 { Value = "A" }, - Owned2 = new OwnedType23211 { Value = "B" } - }); + Owned1 = new OwnedType23211 { Value = "A" }, + Owned2 = new OwnedType23211 { Value = "B" } + }); - context.Add(new SecondOwner23211 - { - Dependents = new List + Add(new SecondOwner23211 + { + Dependents = new List { new SecondDependent23211(), new SecondDependent23211() }, - Owned = new OwnedType23211 { Value = "A" } - }); + Owned = new OwnedType23211 { Value = "A" } + }); - context.SaveChanges(); + SaveChanges(); + } - ClearLog(); - }); + public class Owner23211 + { + public int Id { get; set; } + public List Dependents { get; set; } + public OwnedType23211 Owned1 { get; set; } + public OwnedType23211 Owned2 { get; set; } + } + + public class OwnedType23211 + { + public string Value { get; set; } + } + + public class Dependent23211 + { + public int Id { get; set; } + } + + public class SecondOwner23211 + { + public int Id { get; set; } + public List Dependents { get; set; } + public OwnedType23211 Owned { get; set; } + } + + public class SecondDependent23211 + { + public int Id { get; set; } + } + } #endregion #region Issue10295 [ConditionalFact] - public virtual void Query_filter_with_contains_evaluates_correctly() + public virtual async Task Query_filter_with_contains_evaluates_correctly() { - using (CreateDatabase10295()) + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext10295(_options); var result = context.Entities.ToList(); Assert.Single(result); @@ -9441,7 +8621,7 @@ FROM [Entities] AS [e] } } - public class MyContext10295 : DbContext + protected class MyContext10295 : DbContext { private readonly List _ids = new List { 1, 7 }; @@ -9456,69 +8636,49 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity().HasQueryFilter(x => !_ids.Contains(x.Id)); } - } - public class MyEntity10295 - { - public int Id { get; set; } - public string Name { get; set; } + public void Seed() + { + var e1 = new MyEntity10295 { Name = "Name1" }; + var e2 = new MyEntity10295 { Name = "Name2" }; + Entities.AddRange(e1, e2); + SaveChanges(); + } + + public class MyEntity10295 + { + public int Id { get; set; } + public string Name { get; set; } + } } - private SqlServerTestStore CreateDatabase10295() - => CreateTestStore( - () => new MyContext10295(_options), - context => - { - var e1 = new MyEntity10295 { Name = "Name1" }; - var e2 = new MyEntity10295 { Name = "Name2" }; - context.Entities.AddRange(e1, e2); - context.SaveChanges(); - ClearLog(); - }); #endregion #region Issue23282 [ConditionalFact] - public virtual void Can_query_point_with_buffered_data_reader() + public virtual async Task Can_query_point_with_buffered_data_reader() { - var (options, testSqlLoggerFactory) = CreateOptions23282(); - using var context = new MyContext23282(options); + var contextFactory = await InitializeAsync( + seed: c => c.Seed(), + onConfiguring: o => new SqlServerDbContextOptionsBuilder(o).UseNetTopologySuite(), + addServices: c => c.AddEntityFrameworkSqlServerNetTopologySuite()); - var testUser = context.Locations.FirstOrDefault(x => x.Name == "My Location"); + using (var context = contextFactory.CreateContext()) + { + var testUser = context.Locations.FirstOrDefault(x => x.Name == "My Location"); - Assert.NotNull(testUser); + Assert.NotNull(testUser); - testSqlLoggerFactory.AssertBaseline( - new[] { + AssertSql( + new[] { @"SELECT TOP(1) [l].[Id], [l].[Name], [l].[Address_County], [l].[Address_Line1], [l].[Address_Line2], [l].[Address_Point], [l].[Address_Postcode], [l].[Address_Town] FROM [Locations] AS [l] WHERE [l].[Name] = N'My Location'" }); + } } - [Owned] - private class Address23282 - { - public string Line1 { get; set; } - public string Line2 { get; set; } - public string Town { get; set; } - public string County { get; set; } - public string Postcode { get; set; } - - public Point Point { get; set; } - } - - private class Location23282 - { - [Key] - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public Guid Id { get; set; } - - public string Name { get; set; } - public Address23282 Address { get; set; } - } - - private class MyContext23282 : DbContext + protected class MyContext23282 : DbContext { public DbSet Locations { get; set; } @@ -9526,24 +8686,10 @@ public MyContext23282(DbContextOptions options) : base(options) { } - } - private (DbContextOptions, TestSqlLoggerFactory) CreateOptions23282() - { - var testStore = SqlServerTestStore.CreateInitialized("QueryBugsTest"); - var testSqlLoggerFactory = new TestSqlLoggerFactory(); - var serviceProvider = new ServiceCollection().AddSingleton(testSqlLoggerFactory).BuildServiceProvider(); - - var optionsBuilder = Fixture.AddOptions(new DbContextOptionsBuilder() - .UseSqlServer(testStore.ConnectionString, b => b.EnableRetryOnFailure().UseNetTopologySuite())) - .EnableDetailedErrors() - .EnableServiceProviderCaching(false) - .UseApplicationServiceProvider(serviceProvider); - - var context = new MyContext23282(optionsBuilder.Options); - if (context.Database.EnsureCreatedResiliently()) + public void Seed() { - context.Locations.Add(new Location23282 + Locations.Add(new Location23282 { Name = "My Location", Address = new Address23282 @@ -9555,12 +8701,30 @@ public MyContext23282(DbContextOptions options) Point = new Point(115.7930, 37.2431) { SRID = 4326 } } }); - context.SaveChanges(); + SaveChanges(); + } + + [Owned] + public class Address23282 + { + public string Line1 { get; set; } + public string Line2 { get; set; } + public string Town { get; set; } + public string County { get; set; } + public string Postcode { get; set; } + + public Point Point { get; set; } } - testSqlLoggerFactory.Clear(); + public class Location23282 + { + [Key] + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public Guid Id { get; set; } - return (optionsBuilder.Options, testSqlLoggerFactory); + public string Name { get; set; } + public Address23282 Address { get; set; } + } } #endregion @@ -9568,14 +8732,14 @@ public MyContext23282(DbContextOptions options) #region Issue19253 [ConditionalFact] - public virtual void Concat_combines_nullability_of_entity_shapers() + public virtual async Task Operators_combine_nullability_of_entity_shapers() { - using (CreateDatabase19253()) - { - using var context = new MyContext19253(_options); + var contextFactory = await InitializeAsync(seed: c => c.Seed()); - Expression> leftKeySelector = x => x.forkey; - Expression> rightKeySelector = y => y.forkey; + using (var context = contextFactory.CreateContext()) + { + Expression> leftKeySelector = x => x.forkey; + Expression> rightKeySelector = y => y.forkey; var query = context.A.GroupJoin( context.B, @@ -9588,7 +8752,7 @@ public virtual void Concat_combines_nullability_of_entity_shapers() }) .SelectMany( r => r.rightg.DefaultIfEmpty(), - (x, y) => new JoinResult19253 + (x, y) => new MyContext19253.JoinResult19253 { Left = x.left, Right = y @@ -9600,7 +8764,7 @@ public virtual void Concat_combines_nullability_of_entity_shapers() leftKeySelector, (right, leftg) => new { leftg, right }) .SelectMany(l => l.leftg.DefaultIfEmpty(), - (x, y) => new JoinResult19253 + (x, y) => new MyContext19253.JoinResult19253 { Left = y, Right = x.right @@ -9619,18 +8783,13 @@ UNION ALL FROM [B] AS [b0] LEFT JOIN [A] AS [a0] ON [b0].[forkey] = [a0].[forkey] WHERE [a0].[Id] IS NULL"); + ClearLog(); } - } - [ConditionalFact] - public virtual void Union_combines_nullability_of_entity_shapers() - { - using (CreateDatabase19253()) + using (var context = contextFactory.CreateContext()) { - using var context = new MyContext19253(_options); - - Expression> leftKeySelector = x => x.forkey; - Expression> rightKeySelector = y => y.forkey; + Expression> leftKeySelector = x => x.forkey; + Expression> rightKeySelector = y => y.forkey; var query = context.A.GroupJoin( context.B, @@ -9643,7 +8802,7 @@ public virtual void Union_combines_nullability_of_entity_shapers() }) .SelectMany( r => r.rightg.DefaultIfEmpty(), - (x, y) => new JoinResult19253 + (x, y) => new MyContext19253.JoinResult19253 { Left = x.left, Right = y @@ -9655,7 +8814,7 @@ public virtual void Union_combines_nullability_of_entity_shapers() leftKeySelector, (right, leftg) => new { leftg, right }) .SelectMany(l => l.leftg.DefaultIfEmpty(), - (x, y) => new JoinResult19253 + (x, y) => new MyContext19253.JoinResult19253 { Left = y, Right = x.right @@ -9674,17 +8833,13 @@ FROM [A] AS [a] FROM [B] AS [b0] LEFT JOIN [A] AS [a0] ON [b0].[forkey] = [a0].[forkey] WHERE [a0].[Id] IS NULL"); + ClearLog(); } - } - [ConditionalFact] - public virtual void Except_combines_nullability_of_entity_shapers() - { - using (CreateDatabase19253()) - { - using var context = new MyContext19253(_options); - Expression> leftKeySelector = x => x.forkey; - Expression> rightKeySelector = y => y.forkey; + using (var context = contextFactory.CreateContext()) + { + Expression> leftKeySelector = x => x.forkey; + Expression> rightKeySelector = y => y.forkey; var query = context.A.GroupJoin( context.B, @@ -9697,7 +8852,7 @@ public virtual void Except_combines_nullability_of_entity_shapers() }) .SelectMany( r => r.rightg.DefaultIfEmpty(), - (x, y) => new JoinResult19253 + (x, y) => new MyContext19253.JoinResult19253 { Left = x.left, Right = y @@ -9709,7 +8864,7 @@ public virtual void Except_combines_nullability_of_entity_shapers() leftKeySelector, (right, leftg) => new { leftg, right }) .SelectMany(l => l.leftg.DefaultIfEmpty(), - (x, y) => new JoinResult19253 + (x, y) => new MyContext19253.JoinResult19253 { Left = y, Right = x.right @@ -9726,17 +8881,13 @@ FROM [A] AS [a] SELECT [a0].[Id], [a0].[a], [a0].[a1], [a0].[forkey], [b0].[Id] AS [Id0], [b0].[b], [b0].[b1], [b0].[forkey] AS [forkey0] FROM [B] AS [b0] LEFT JOIN [A] AS [a0] ON [b0].[forkey] = [a0].[forkey]"); + ClearLog(); } - } - [ConditionalFact] - public virtual void Intersect_combines_nullability_of_entity_shapers() - { - using (CreateDatabase19253()) - { - using var context = new MyContext19253(_options); - Expression> leftKeySelector = x => x.forkey; - Expression> rightKeySelector = y => y.forkey; + using (var context = contextFactory.CreateContext()) + { + Expression> leftKeySelector = x => x.forkey; + Expression> rightKeySelector = y => y.forkey; var query = context.A.GroupJoin( context.B, @@ -9749,7 +8900,7 @@ public virtual void Intersect_combines_nullability_of_entity_shapers() }) .SelectMany( r => r.rightg.DefaultIfEmpty(), - (x, y) => new JoinResult19253 + (x, y) => new MyContext19253.JoinResult19253 { Left = x.left, Right = y @@ -9761,7 +8912,7 @@ public virtual void Intersect_combines_nullability_of_entity_shapers() leftKeySelector, (right, leftg) => new { leftg, right }) .SelectMany(l => l.leftg.DefaultIfEmpty(), - (x, y) => new JoinResult19253 + (x, y) => new MyContext19253.JoinResult19253 { Left = y, Right = x.right @@ -9791,52 +8942,48 @@ public MyContext19253(DbContextOptions options) : base(options) { } - } - - public class JoinResult19253 - { - public TLeft Left { get; set; } - - public TRight Right { get; set; } - } - - public class A19253 - { - public int Id { get; set; } - public string a { get; set; } - public string a1 { get; set; } - public string forkey { get; set; } - - } - - public class B19253 - { - public int Id { get; set; } - public string b { get; set; } - public string b1 { get; set; } - public string forkey { get; set; } - } - private SqlServerTestStore CreateDatabase19253() - => CreateTestStore( - () => new MyContext19253(_options), - context => + public void Seed() + { + var tmp_a = new A19253[] { - var tmp_a = new A19253[] - { new A19253 {a = "a0", a1 = "a1", forkey = "a"}, new A19253 {a = "a2", a1 = "a1", forkey = "d"}, - }; - var tmp_b = new B19253[] - { + }; + var tmp_b = new B19253[] + { new B19253 {b = "b0", b1 = "b1", forkey = "a"}, new B19253 {b = "b2", b1 = "b1", forkey = "c"}, - }; - context.A.AddRange(tmp_a); - context.B.AddRange(tmp_b); - context.SaveChanges(); - ClearLog(); - }); + }; + A.AddRange(tmp_a); + B.AddRange(tmp_b); + SaveChanges(); + } + + public class JoinResult19253 + { + public TLeft Left { get; set; } + + public TRight Right { get; set; } + } + + public class A19253 + { + public int Id { get; set; } + public string a { get; set; } + public string a1 { get; set; } + public string forkey { get; set; } + + } + + public class B19253 + { + public int Id { get; set; } + public string b { get; set; } + public string b1 { get; set; } + public string forkey { get; set; } + } + } #endregion @@ -9845,31 +8992,27 @@ private SqlServerTestStore CreateDatabase19253() // TODO: Remove when JSON is first class. See issue#4021 [ConditionalFact] - public virtual void Method_call_translators_are_invoked_for_indexer_if_not_indexer_property() + public virtual async Task Method_call_translators_are_invoked_for_indexer_if_not_indexer_property() { - var (options, testSqlLoggerFactory) = CreateOptions23410(); - using var context = new MyContext23410(options); + var contextFactory = await InitializeAsync(seed: c => c.Seed(), + addServices: c => c.TryAddEnumerable(new ServiceDescriptor( + typeof(IMethodCallTranslatorPlugin), typeof(MyContext23410.JsonMethodCallTranslatorPlugin), ServiceLifetime.Singleton))); - var testUser = context.Blogs.FirstOrDefault(x => x.JObject["Author"].Value() == "Maumar"); + using (var context = contextFactory.CreateContext()) + { + var testUser = context.Blogs.FirstOrDefault(x => x.JObject["Author"].Value() == "Maumar"); - Assert.NotNull(testUser); + Assert.NotNull(testUser); - testSqlLoggerFactory.AssertBaseline( - new[] { + AssertSql( + new[] { @"SELECT TOP(1) [b].[Id], [b].[JObject], [b].[Name] FROM [Blogs] AS [b] WHERE JSON_VALUE([b].[JObject], '$.Author') = N'Maumar'" }); + } } - private class Blog23410 - { - public int Id { get; set; } - - public string Name { get; set; } - public JObject JObject { get; set; } - } - - private class MyContext23410 : DbContext + protected class MyContext23410 : DbContext { public DbSet Blogs { get; set; } @@ -9884,151 +9027,153 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) e => e.ToString(), e => JObject.Parse(e)); } - } - private class JsonMethodCallTranslatorPlugin : IMethodCallTranslatorPlugin - { - public JsonMethodCallTranslatorPlugin(ISqlExpressionFactory sqlExpressionFactory) + public void Seed() { - Translators = new IMethodCallTranslator[] + Blogs.Add(new Blog23410 { - new JsonIndexerMethodTranslator(sqlExpressionFactory), - new JsonValueMethodTranslator(sqlExpressionFactory) - }; + Name = "My Location", + JObject = JObject.Parse(@"{ ""Author"": ""Maumar"" }") + }); + SaveChanges(); } - public IEnumerable Translators { get; } - } - - private class JsonValueMethodTranslator : IMethodCallTranslator - { - private readonly ISqlExpressionFactory _sqlExpressionFactory; - - public JsonValueMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) + public class Blog23410 { - _sqlExpressionFactory = sqlExpressionFactory; + public int Id { get; set; } + + public string Name { get; set; } + public JObject JObject { get; set; } } - public SqlExpression Translate( - SqlExpression instance, - MethodInfo method, - IReadOnlyList arguments, - IDiagnosticsLogger logger) + public class JsonMethodCallTranslatorPlugin : IMethodCallTranslatorPlugin { - if (method.IsGenericMethod - && method.DeclaringType == typeof(Newtonsoft.Json.Linq.Extensions) - && method.Name == "Value" - && arguments.Count == 1 - && arguments[0] is SqlFunctionExpression sqlFunctionExpression) + public JsonMethodCallTranslatorPlugin(ISqlExpressionFactory sqlExpressionFactory) { - return _sqlExpressionFactory.Function( - sqlFunctionExpression.Name, - sqlFunctionExpression.Arguments, - sqlFunctionExpression.IsNullable, - sqlFunctionExpression.ArgumentsPropagateNullability, - method.ReturnType); + Translators = new IMethodCallTranslator[] + { + new JsonIndexerMethodTranslator(sqlExpressionFactory), + new JsonValueMethodTranslator(sqlExpressionFactory) + }; } - return null; + public IEnumerable Translators { get; } } - } - - private class JsonIndexerMethodTranslator : IMethodCallTranslator - { - private readonly MethodInfo _indexerMethod = typeof(JObject).GetRuntimeMethod("get_Item", new[] { typeof(string) }); - - private readonly ISqlExpressionFactory _sqlExpressionFactory; - public JsonIndexerMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) + private class JsonValueMethodTranslator : IMethodCallTranslator { - _sqlExpressionFactory = sqlExpressionFactory; - } + private readonly ISqlExpressionFactory _sqlExpressionFactory; - public SqlExpression Translate( - SqlExpression instance, - MethodInfo method, - IReadOnlyList arguments, - IDiagnosticsLogger logger) - { - if (Equals(_indexerMethod, method)) + public JsonValueMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) { - return _sqlExpressionFactory.Function( - "JSON_VALUE", - new[] { - instance, - _sqlExpressionFactory.Fragment($"'$.{((SqlConstantExpression)arguments[0]).Value}'") - }, - nullable: true, - argumentsPropagateNullability: new[] { true, false }, - _indexerMethod.ReturnType); + _sqlExpressionFactory = sqlExpressionFactory; } - return null; + public SqlExpression Translate( + SqlExpression instance, + MethodInfo method, + IReadOnlyList arguments, + IDiagnosticsLogger logger) + { + if (method.IsGenericMethod + && method.DeclaringType == typeof(Newtonsoft.Json.Linq.Extensions) + && method.Name == "Value" + && arguments.Count == 1 + && arguments[0] is SqlFunctionExpression sqlFunctionExpression) + { + return _sqlExpressionFactory.Function( + sqlFunctionExpression.Name, + sqlFunctionExpression.Arguments, + sqlFunctionExpression.IsNullable, + sqlFunctionExpression.ArgumentsPropagateNullability, + method.ReturnType); + } + + return null; + } } - } - private (DbContextOptions, TestSqlLoggerFactory) CreateOptions23410() - { - var testStore = SqlServerTestStore.CreateInitialized("QueryBugsTest"); - var testSqlLoggerFactory = new TestSqlLoggerFactory(); - var serviceCollection = new ServiceCollection() - .AddSingleton(testSqlLoggerFactory) - .AddEntityFrameworkSqlServer(); - serviceCollection.TryAddEnumerable(new ServiceDescriptor( - typeof(IMethodCallTranslatorPlugin), typeof(JsonMethodCallTranslatorPlugin), ServiceLifetime.Singleton)); - var serviceProvider = serviceCollection.BuildServiceProvider(); + private class JsonIndexerMethodTranslator : IMethodCallTranslator + { + private readonly MethodInfo _indexerMethod = typeof(JObject).GetRuntimeMethod("get_Item", new[] { typeof(string) }); - var optionsBuilder = Fixture.AddOptions(testStore.AddProviderOptions(new DbContextOptionsBuilder())) - .EnableDetailedErrors() - .UseInternalServiceProvider(serviceProvider) - .EnableServiceProviderCaching(false); + private readonly ISqlExpressionFactory _sqlExpressionFactory; - var context = new MyContext23410(optionsBuilder.Options); - if (context.Database.EnsureCreatedResiliently()) - { - context.Blogs.Add(new Blog23410 + public JsonIndexerMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) { - Name = "My Location", - JObject = JObject.Parse(@"{ ""Author"": ""Maumar"" }") - }); - context.SaveChanges(); - } + _sqlExpressionFactory = sqlExpressionFactory; + } - testSqlLoggerFactory.Clear(); + public SqlExpression Translate( + SqlExpression instance, + MethodInfo method, + IReadOnlyList arguments, + IDiagnosticsLogger logger) + { + if (Equals(_indexerMethod, method)) + { + return _sqlExpressionFactory.Function( + "JSON_VALUE", + new[] { + instance, + _sqlExpressionFactory.Fragment($"'$.{((SqlConstantExpression)arguments[0]).Value}'") + }, + nullable: true, + argumentsPropagateNullability: new[] { true, false }, + _indexerMethod.ReturnType); + } - return (optionsBuilder.Options, testSqlLoggerFactory); + return null; + } + } } #endregion - private DbContextOptions _options; + protected override string StoreName => "QueryBugsTest"; + protected TestSqlLoggerFactory TestSqlLoggerFactory + => (TestSqlLoggerFactory)ListLoggerFactory; + protected override ITestStoreFactory TestStoreFactory + => SqlServerTestStoreFactory.Instance; + protected override DbContextOptionsBuilder AddOptions(DbContextOptionsBuilder builder) + => base.AddOptions(builder).ConfigureWarnings( + w => + { + w.Log(SqlServerEventId.ByteIdentityColumnWarning); + w.Log(SqlServerEventId.DecimalTypeKeyWarning); + }); - private SqlServerTestStore CreateTestStore( - Func contextCreator, - Action contextInitializer) - where TContext : DbContext, IDisposable - { - var testStore = SqlServerTestStore.CreateInitialized("QueryBugsTest", multipleActiveResultSets: true); + protected override TestStore CreateTestStore() + => SqlServerTestStore.CreateInitialized(StoreName, multipleActiveResultSets: true); - _options = Fixture.CreateOptions(testStore); + private static readonly FieldInfo querySplittingBehaviorFieldInfo = + typeof(RelationalOptionsExtension).GetField("_querySplittingBehavior", BindingFlags.NonPublic | BindingFlags.Instance); - using (var context = contextCreator()) + protected DbContextOptionsBuilder ClearQuerySplittingBehavior(DbContextOptionsBuilder optionsBuilder) + { + var extension = optionsBuilder.Options.FindExtension(); + if (extension == null) { - context.Database.EnsureCreatedResiliently(); - contextInitializer?.Invoke(context); + extension = new SqlServerOptionsExtension(); + } + else + { + querySplittingBehaviorFieldInfo.SetValue(extension, null); } - return testStore; + ((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension); + + return optionsBuilder; } protected void ClearLog() { - Fixture.TestSqlLoggerFactory.Clear(); + TestSqlLoggerFactory.Clear(); } - private void AssertSql(params string[] expected) + protected void AssertSql(params string[] expected) { - Fixture.TestSqlLoggerFactory.AssertBaseline(expected); + TestSqlLoggerFactory.AssertBaseline(expected); } } } diff --git a/test/EFCore.SqlServer.FunctionalTests/TPTTableSplittingSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/TPTTableSplittingSqlServerTest.cs index 8f83e1263d1..8a5932e5d33 100644 --- a/test/EFCore.SqlServer.FunctionalTests/TPTTableSplittingSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/TPTTableSplittingSqlServerTest.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Threading.Tasks; using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit.Abstractions; @@ -16,9 +17,9 @@ public TPTTableSplittingSqlServerTest(ITestOutputHelper testOutputHelper) protected override ITestStoreFactory TestStoreFactory => SqlServerTestStoreFactory.Instance; - public override void Can_use_with_redundant_relationships() + public override async Task Can_use_with_redundant_relationships() { - base.Can_use_with_redundant_relationships(); + await base.Can_use_with_redundant_relationships(); AssertSql( @"SELECT [v].[Name], [v].[SeatingCapacity], [c].[AttachedVehicleName], CASE @@ -85,9 +86,9 @@ WHERE [c5].[FuelType] IS NOT NULL OR [c5].[Capacity] IS NOT NULL ORDER BY [v].[Name]"); } - public override void Can_query_shared() + public override async Task Can_query_shared() { - base.Can_query_shared(); + await base.Can_query_shared(); AssertSql( @"SELECT [v].[Name], [v].[Operator_Name], [l].[LicenseType], CASE @@ -101,9 +102,9 @@ FROM [Vehicles] AS [v0] ) AS [t] ON [v].[Name] = [t].[Name]"); } - public override void Can_query_shared_nonhierarchy() + public override async Task Can_query_shared_nonhierarchy() { - base.Can_query_shared_nonhierarchy(); + await base.Can_query_shared_nonhierarchy(); AssertSql( @"SELECT [v].[Name], [v].[Operator_Name] @@ -114,9 +115,9 @@ FROM [Vehicles] AS [v0] ) AS [t] ON [v].[Name] = [t].[Name]"); } - public override void Can_query_shared_nonhierarchy_with_nonshared_dependent() + public override async Task Can_query_shared_nonhierarchy_with_nonshared_dependent() { - base.Can_query_shared_nonhierarchy_with_nonshared_dependent(); + await base.Can_query_shared_nonhierarchy_with_nonshared_dependent(); AssertSql( @"SELECT [v].[Name], [v].[Operator_Name] @@ -127,9 +128,9 @@ FROM [Vehicles] AS [v0] ) AS [t] ON [v].[Name] = [t].[Name]"); } - public override void Can_query_shared_derived_hierarchy() + public override async Task Can_query_shared_derived_hierarchy() { - base.Can_query_shared_derived_hierarchy(); + await base.Can_query_shared_derived_hierarchy(); AssertSql( @"SELECT [c].[VehicleName], [c].[Capacity], [c].[FuelType], [s].[GrainGeometry], CASE @@ -145,9 +146,9 @@ FROM [PoweredVehicles] AS [p] WHERE [c].[FuelType] IS NOT NULL OR [c].[Capacity] IS NOT NULL"); } - public override void Can_query_shared_derived_nonhierarchy() + public override async Task Can_query_shared_derived_nonhierarchy() { - base.Can_query_shared_derived_nonhierarchy(); + await base.Can_query_shared_derived_nonhierarchy(); AssertSql( @"SELECT [c].[VehicleName], [c].[Capacity], [c].[FuelType] @@ -160,9 +161,9 @@ FROM [PoweredVehicles] AS [p] WHERE [c].[FuelType] IS NOT NULL OR [c].[Capacity] IS NOT NULL"); } - public override void Can_query_shared_derived_nonhierarchy_all_required() + public override async Task Can_query_shared_derived_nonhierarchy_all_required() { - base.Can_query_shared_derived_nonhierarchy_all_required(); + await base.Can_query_shared_derived_nonhierarchy_all_required(); AssertSql( @"SELECT [c].[VehicleName], [c].[Capacity], [c].[FuelType] @@ -175,9 +176,9 @@ FROM [PoweredVehicles] AS [p] WHERE [c].[FuelType] IS NOT NULL AND [c].[Capacity] IS NOT NULL"); } - public override void Can_change_dependent_instance_non_derived() + public override async Task Can_change_dependent_instance_non_derived() { - base.Can_change_dependent_instance_non_derived(); + await base.Can_change_dependent_instance_non_derived(); AssertSql( @"@p0='Trek Pro Fit Madone 6 Series' (Nullable = false) (Size = 450) @p1='Repair' (Size = 4000) @@ -215,9 +216,9 @@ FROM [Vehicles] AS [v1] WHERE [v].[Name] = N'Trek Pro Fit Madone 6 Series'"); } - public override void Can_change_principal_instance_non_derived() + public override async Task Can_change_principal_instance_non_derived() { - base.Can_change_principal_instance_non_derived(); + await base.Can_change_principal_instance_non_derived(); AssertSql( @"@p1='Trek Pro Fit Madone 6 Series' (Nullable = false) (Size = 450) diff --git a/test/EFCore.SqlServer.FunctionalTests/TableSplittingSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/TableSplittingSqlServerTest.cs index dcc53e7e3a8..975faf955ae 100644 --- a/test/EFCore.SqlServer.FunctionalTests/TableSplittingSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/TableSplittingSqlServerTest.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Threading.Tasks; using Microsoft.EntityFrameworkCore.TestModels.TransportationModel; using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit.Abstractions; @@ -17,9 +18,9 @@ public TableSplittingSqlServerTest(ITestOutputHelper testOutputHelper) protected override ITestStoreFactory TestStoreFactory => SqlServerTestStoreFactory.Instance; - public override void Can_use_with_redundant_relationships() + public override async Task Can_use_with_redundant_relationships() { - base.Can_use_with_redundant_relationships(); + await base.Can_use_with_redundant_relationships(); // TODO: [Name] shouldn't be selected multiple times and no joins are needed AssertSql( @@ -77,9 +78,9 @@ WHERE [v9].[FuelTank_Discriminator] IS NOT NULL ORDER BY [v].[Name]"); } - public override void Can_query_shared() + public override async Task Can_query_shared() { - base.Can_query_shared(); + await base.Can_query_shared(); AssertSql( @"SELECT [v].[Name], [v].[Operator_Discriminator], [v].[Operator_Name], [v].[LicenseType] @@ -87,9 +88,9 @@ FROM [Vehicles] AS [v] INNER JOIN [Vehicles] AS [v0] ON [v].[Name] = [v0].[Name]"); } - public override void Can_query_shared_nonhierarchy() + public override async Task Can_query_shared_nonhierarchy() { - base.Can_query_shared_nonhierarchy(); + await base.Can_query_shared_nonhierarchy(); AssertSql( @"SELECT [v].[Name], [v].[Operator_Name] @@ -97,9 +98,9 @@ FROM [Vehicles] AS [v] INNER JOIN [Vehicles] AS [v0] ON [v].[Name] = [v0].[Name]"); } - public override void Can_query_shared_nonhierarchy_with_nonshared_dependent() + public override async Task Can_query_shared_nonhierarchy_with_nonshared_dependent() { - base.Can_query_shared_nonhierarchy_with_nonshared_dependent(); + await base.Can_query_shared_nonhierarchy_with_nonshared_dependent(); AssertSql( @"SELECT [v].[Name], [v].[Operator_Name] @@ -107,9 +108,9 @@ FROM [Vehicles] AS [v] INNER JOIN [Vehicles] AS [v0] ON [v].[Name] = [v0].[Name]"); } - public override void Can_query_shared_derived_hierarchy() + public override async Task Can_query_shared_derived_hierarchy() { - base.Can_query_shared_derived_hierarchy(); + await base.Can_query_shared_derived_hierarchy(); AssertSql( @"SELECT [v].[Name], [v].[Capacity], [v].[FuelTank_Discriminator], [v].[FuelType], [v].[GrainGeometry] @@ -136,9 +137,9 @@ WHERE [v2].[Engine_Discriminator] IN (N'ContinuousCombustionEngine', N'Intermitt WHERE [v1].[FuelTank_Discriminator] IS NOT NULL"); } - public override void Can_query_shared_derived_nonhierarchy() + public override async Task Can_query_shared_derived_nonhierarchy() { - base.Can_query_shared_derived_nonhierarchy(); + await base.Can_query_shared_derived_nonhierarchy(); AssertSql( @"SELECT [v].[Name], [v].[Capacity], [v].[FuelType] @@ -165,9 +166,9 @@ WHERE [v2].[Engine_Discriminator] IN (N'ContinuousCombustionEngine', N'Intermitt WHERE [v1].[FuelType] IS NOT NULL OR [v1].[Capacity] IS NOT NULL"); } - public override void Can_query_shared_derived_nonhierarchy_all_required() + public override async Task Can_query_shared_derived_nonhierarchy_all_required() { - base.Can_query_shared_derived_nonhierarchy_all_required(); + await base.Can_query_shared_derived_nonhierarchy_all_required(); AssertSql( @"SELECT [v].[Name], [v].[Capacity], [v].[FuelType] @@ -194,9 +195,9 @@ WHERE [v2].[Engine_Discriminator] IN (N'ContinuousCombustionEngine', N'Intermitt WHERE [v1].[FuelType] IS NOT NULL AND [v1].[Capacity] IS NOT NULL"); } - public override void Can_change_dependent_instance_non_derived() + public override async Task Can_change_dependent_instance_non_derived() { - base.Can_change_dependent_instance_non_derived(); + await base.Can_change_dependent_instance_non_derived(); AssertSql( @"@p3='Trek Pro Fit Madone 6 Series' (Nullable = false) (Size = 450) @@ -219,9 +220,9 @@ FROM [Vehicles] AS [v0] WHERE [v].[Name] = N'Trek Pro Fit Madone 6 Series'"); } - public override void Can_change_principal_instance_non_derived() + public override async Task Can_change_principal_instance_non_derived() { - base.Can_change_principal_instance_non_derived(); + await base.Can_change_principal_instance_non_derived(); AssertSql( @"@p1='Trek Pro Fit Madone 6 Series' (Nullable = false) (Size = 450)