Skip to content

Commit

Permalink
Added tests for EF Core table-per-concrete-type inheritance mode
Browse files Browse the repository at this point in the history
  • Loading branch information
bkoelman committed Jan 31, 2023
1 parent f0b6a2d commit ab8759c
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2298,7 +2298,7 @@ public async Task Can_add_concrete_base_resources_stored_as_derived_at_ToMany_re

await _testContext.RunOnDatabaseAsync(async dbContext =>
{
dbContext.Set<VehicleManufacturer>().Add(existingManufacturer);
dbContext.VehicleManufacturers.Add(existingManufacturer);
dbContext.Vehicles.Add(existingTandem);
await dbContext.SaveChangesAsync();
});
Expand Down Expand Up @@ -2327,9 +2327,17 @@ public async Task Can_add_concrete_base_resources_stored_as_derived_at_ToMany_re

await _testContext.RunOnDatabaseAsync(async dbContext =>
{
VehicleManufacturer manufacturerInDatabase = await dbContext.Set<VehicleManufacturer>().Include(manufacturer => manufacturer.Vehicles)
// @formatter:wrap_chained_method_calls chop_always
// @formatter:keep_existing_linebreaks true
VehicleManufacturer manufacturerInDatabase = await dbContext.VehicleManufacturers
.Include(manufacturer => manufacturer.Vehicles
.OrderByDescending(vehicle => vehicle.Id))
.FirstWithIdAsync(existingManufacturer.Id);
// @formatter:keep_existing_linebreaks restore
// @formatter:wrap_chained_method_calls restore
manufacturerInDatabase.Vehicles.ShouldHaveCount(2);
manufacturerInDatabase.Vehicles.ElementAt(0).Should().BeOfType<Car>();
manufacturerInDatabase.Vehicles.ElementAt(0).Id.Should().Be(existingManufacturer.Vehicles.ElementAt(0).Id);
Expand Down Expand Up @@ -2578,7 +2586,7 @@ public async Task Can_remove_concrete_base_resources_stored_as_derived_at_ToMany

await _testContext.RunOnDatabaseAsync(async dbContext =>
{
dbContext.Set<VehicleManufacturer>().Add(existingManufacturer);
dbContext.VehicleManufacturers.Add(existingManufacturer);
await dbContext.SaveChangesAsync();
});

Expand Down Expand Up @@ -2606,7 +2614,7 @@ public async Task Can_remove_concrete_base_resources_stored_as_derived_at_ToMany

await _testContext.RunOnDatabaseAsync(async dbContext =>
{
VehicleManufacturer manufacturerInDatabase = await dbContext.Set<VehicleManufacturer>().Include(manufacturer => manufacturer.Vehicles)
VehicleManufacturer manufacturerInDatabase = await dbContext.VehicleManufacturers.Include(manufacturer => manufacturer.Vehicles)
.FirstWithIdAsync(existingManufacturer.Id);
manufacturerInDatabase.Vehicles.ShouldHaveCount(1);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using JetBrains.Annotations;
using JsonApiDotNetCoreTests.IntegrationTests.ResourceInheritance.Models;
using Microsoft.EntityFrameworkCore;

// @formatter:wrap_chained_method_calls chop_always

namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceInheritance.TablePerConcreteType;

[UsedImplicitly(ImplicitUseTargetFlags.Members)]
public sealed class TablePerConcreteTypeDbContext : ResourceInheritanceDbContext
{
public TablePerConcreteTypeDbContext(DbContextOptions<TablePerConcreteTypeDbContext> options)
: base(options)
{
}

protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Vehicle>()
.UseTpcMappingStrategy();

builder.Entity<Wheel>()
.UseTpcMappingStrategy();

builder.Entity<Engine>()
.UseTpcMappingStrategy();

builder.Entity<GenericProperty>()
.UseTpcMappingStrategy();

base.OnModelCreating(builder);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using JetBrains.Annotations;
using TestBuildingBlocks;

namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceInheritance.TablePerConcreteType;

[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)]
public sealed class TablePerConcreteTypeReadTests : ResourceInheritanceReadTests<TablePerConcreteTypeDbContext>
{
public TablePerConcreteTypeReadTests(IntegrationTestContext<TestableStartup<TablePerConcreteTypeDbContext>, TablePerConcreteTypeDbContext> testContext)
: base(testContext)
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using JetBrains.Annotations;
using TestBuildingBlocks;

namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceInheritance.TablePerConcreteType;

[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)]
public sealed class TablePerConcreteTypeWriteTests : ResourceInheritanceWriteTests<TablePerConcreteTypeDbContext>
{
public TablePerConcreteTypeWriteTests(IntegrationTestContext<TestableStartup<TablePerConcreteTypeDbContext>, TablePerConcreteTypeDbContext> testContext)
: base(testContext)
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using JsonApiDotNetCoreTests.IntegrationTests.ResourceInheritance.Models;
using Microsoft.EntityFrameworkCore;

// @formatter:wrap_chained_method_calls chop_always

namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceInheritance.TablePerType;

[UsedImplicitly(ImplicitUseTargetFlags.Members)]
Expand All @@ -14,24 +16,17 @@ public TablePerTypeDbContext(DbContextOptions<TablePerTypeDbContext> options)

protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Vehicle>().ToTable("Vehicles");
builder.Entity<Bike>().ToTable("Bikes");
builder.Entity<Tandem>().ToTable("Tandems");
builder.Entity<MotorVehicle>().ToTable("MotorVehicles");
builder.Entity<Car>().ToTable("Cars");
builder.Entity<Truck>().ToTable("Trucks");

builder.Entity<Wheel>().ToTable("Wheels");
builder.Entity<CarbonWheel>().ToTable("CarbonWheels");
builder.Entity<ChromeWheel>().ToTable("ChromeWheels");

builder.Entity<Engine>().ToTable("Engines");
builder.Entity<GasolineEngine>().ToTable("GasolineEngines");
builder.Entity<DieselEngine>().ToTable("DieselEngines");

builder.Entity<GenericProperty>().ToTable("GenericProperties");
builder.Entity<StringProperty>().ToTable("StringProperties");
builder.Entity<NumberProperty>().ToTable("NumberProperties");
builder.Entity<Vehicle>()
.UseTptMappingStrategy();

builder.Entity<Wheel>()
.UseTptMappingStrategy();

builder.Entity<Engine>()
.UseTptMappingStrategy();

builder.Entity<GenericProperty>()
.UseTptMappingStrategy();

base.OnModelCreating(builder);
}
Expand Down
14 changes: 12 additions & 2 deletions test/TestBuildingBlocks/DbContextExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,18 @@ private static async Task ClearTablesAsync(this DbContext dbContext, params Type
throw new InvalidOperationException($"Table for '{model.Name}' not found.");
}

string tableName = entityType.GetTableName()!;
await dbContext.Database.ExecuteSqlRawAsync($"delete from \"{tableName}\"");
string? tableName = entityType.GetTableName();

if (tableName == null)
{
// There is no table for the specified abstract base type when using TablePerConcreteType inheritance.
IEnumerable<IEntityType> derivedTypes = entityType.GetConcreteDerivedTypesInclusive();
await ClearTablesAsync(dbContext, derivedTypes.Select(derivedType => derivedType.ClrType).ToArray());
}
else
{
await dbContext.Database.ExecuteSqlRawAsync($"delete from \"{tableName}\"");
}
}
}
}

0 comments on commit ab8759c

Please sign in to comment.