diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index f8589a73a7..da7dc3dede 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -9,7 +9,7 @@ ] }, "regitlint": { - "version": "6.2.1", + "version": "6.3.10", "commands": [ "regitlint" ] @@ -21,7 +21,7 @@ ] }, "dotnet-reportgenerator-globaltool": { - "version": "5.1.11", + "version": "5.1.15", "commands": [ "reportgenerator" ] diff --git a/Directory.Build.props b/Directory.Build.props index d641e8d6b6..15a7e94c7c 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,9 +2,9 @@ net6.0 6.0.* - 6.0.* - 6.0.* - 4.3.* + 7.0.* + 7.0.* + 4.4.* 2.14.1 5.1.2 $(MSBuildThisFileDirectory)CodingGuidelines.ruleset @@ -33,8 +33,8 @@ - 3.2.0 - 4.18.2 - 17.4.0 + 3.2.* + 4.18.* + 17.4.* diff --git a/benchmarks/Benchmarks.csproj b/benchmarks/Benchmarks.csproj index 3958713af4..185f2919ac 100644 --- a/benchmarks/Benchmarks.csproj +++ b/benchmarks/Benchmarks.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/Examples/JsonApiDotNetCoreExample/Program.cs b/src/Examples/JsonApiDotNetCoreExample/Program.cs index bda826d131..e2fbc66ffd 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Program.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Program.cs @@ -47,7 +47,7 @@ static void ConfigureServices(WebApplicationBuilder builder) builder.Services.AddDbContext(options => { - string connectionString = GetConnectionString(builder.Configuration); + string? connectionString = GetConnectionString(builder.Configuration); options.UseNpgsql(connectionString); #if DEBUG @@ -73,10 +73,10 @@ static void ConfigureServices(WebApplicationBuilder builder) } } -static string GetConnectionString(IConfiguration configuration) +static string? GetConnectionString(IConfiguration configuration) { string postgresPassword = Environment.GetEnvironmentVariable("PGPASSWORD") ?? "postgres"; - return configuration["Data:DefaultConnection"].Replace("###", postgresPassword); + return configuration["Data:DefaultConnection"]?.Replace("###", postgresPassword); } static void ConfigurePipeline(WebApplication webApplication) diff --git a/src/Examples/NoEntityFrameworkExample/Program.cs b/src/Examples/NoEntityFrameworkExample/Program.cs index 43a14f7896..363b58b19e 100755 --- a/src/Examples/NoEntityFrameworkExample/Program.cs +++ b/src/Examples/NoEntityFrameworkExample/Program.cs @@ -7,7 +7,7 @@ // Add services to the container. -string connectionString = GetConnectionString(builder.Configuration); +string? connectionString = GetConnectionString(builder.Configuration); builder.Services.AddNpgsql(connectionString); builder.Services.AddJsonApi(options => options.Namespace = "api/v1", resources: resourceGraphBuilder => resourceGraphBuilder.Add()); @@ -26,10 +26,10 @@ app.Run(); -static string GetConnectionString(IConfiguration configuration) +static string? GetConnectionString(IConfiguration configuration) { string postgresPassword = Environment.GetEnvironmentVariable("PGPASSWORD") ?? "postgres"; - return configuration["Data:DefaultConnection"].Replace("###", postgresPassword); + return configuration["Data:DefaultConnection"]?.Replace("###", postgresPassword); } static async Task CreateDatabaseAsync(IServiceProvider serviceProvider) diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceWriteTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceWriteTests.cs index 0dd9659593..c3d7f1fb9c 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceWriteTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/ResourceInheritanceWriteTests.cs @@ -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().Add(existingManufacturer); + dbContext.VehicleManufacturers.Add(existingManufacturer); dbContext.Vehicles.Add(existingTandem); await dbContext.SaveChangesAsync(); }); @@ -2327,9 +2327,17 @@ await _testContext.RunOnDatabaseAsync(async dbContext => await _testContext.RunOnDatabaseAsync(async dbContext => { - VehicleManufacturer manufacturerInDatabase = await dbContext.Set().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(); manufacturerInDatabase.Vehicles.ElementAt(0).Id.Should().Be(existingManufacturer.Vehicles.ElementAt(0).Id); @@ -2578,7 +2586,7 @@ public async Task Can_remove_concrete_base_resources_stored_as_derived_at_ToMany await _testContext.RunOnDatabaseAsync(async dbContext => { - dbContext.Set().Add(existingManufacturer); + dbContext.VehicleManufacturers.Add(existingManufacturer); await dbContext.SaveChangesAsync(); }); @@ -2606,7 +2614,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => await _testContext.RunOnDatabaseAsync(async dbContext => { - VehicleManufacturer manufacturerInDatabase = await dbContext.Set().Include(manufacturer => manufacturer.Vehicles) + VehicleManufacturer manufacturerInDatabase = await dbContext.VehicleManufacturers.Include(manufacturer => manufacturer.Vehicles) .FirstWithIdAsync(existingManufacturer.Id); manufacturerInDatabase.Vehicles.ShouldHaveCount(1); diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerConcreteType/TablePerConcreteTypeDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerConcreteType/TablePerConcreteTypeDbContext.cs new file mode 100644 index 0000000000..2b5977c8b4 --- /dev/null +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerConcreteType/TablePerConcreteTypeDbContext.cs @@ -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 options) + : base(options) + { + } + + protected override void OnModelCreating(ModelBuilder builder) + { + builder.Entity() + .UseTpcMappingStrategy(); + + builder.Entity() + .UseTpcMappingStrategy(); + + builder.Entity() + .UseTpcMappingStrategy(); + + builder.Entity() + .UseTpcMappingStrategy(); + + base.OnModelCreating(builder); + } +} diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerConcreteType/TablePerConcreteTypeReadTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerConcreteType/TablePerConcreteTypeReadTests.cs new file mode 100644 index 0000000000..bcffe2ed5e --- /dev/null +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerConcreteType/TablePerConcreteTypeReadTests.cs @@ -0,0 +1,13 @@ +using JetBrains.Annotations; +using TestBuildingBlocks; + +namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceInheritance.TablePerConcreteType; + +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +public sealed class TablePerConcreteTypeReadTests : ResourceInheritanceReadTests +{ + public TablePerConcreteTypeReadTests(IntegrationTestContext, TablePerConcreteTypeDbContext> testContext) + : base(testContext) + { + } +} diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerConcreteType/TablePerConcreteTypeWriteTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerConcreteType/TablePerConcreteTypeWriteTests.cs new file mode 100644 index 0000000000..9f2e3c3cae --- /dev/null +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerConcreteType/TablePerConcreteTypeWriteTests.cs @@ -0,0 +1,13 @@ +using JetBrains.Annotations; +using TestBuildingBlocks; + +namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceInheritance.TablePerConcreteType; + +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +public sealed class TablePerConcreteTypeWriteTests : ResourceInheritanceWriteTests +{ + public TablePerConcreteTypeWriteTests(IntegrationTestContext, TablePerConcreteTypeDbContext> testContext) + : base(testContext) + { + } +} diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerType/TablePerTypeDbContext.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerType/TablePerTypeDbContext.cs index 7c50ee5573..86a723bfd3 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerType/TablePerTypeDbContext.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/TablePerType/TablePerTypeDbContext.cs @@ -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)] @@ -14,24 +16,17 @@ public TablePerTypeDbContext(DbContextOptions options) protected override void OnModelCreating(ModelBuilder builder) { - builder.Entity().ToTable("Vehicles"); - builder.Entity().ToTable("Bikes"); - builder.Entity().ToTable("Tandems"); - builder.Entity().ToTable("MotorVehicles"); - builder.Entity().ToTable("Cars"); - builder.Entity().ToTable("Trucks"); - - builder.Entity().ToTable("Wheels"); - builder.Entity().ToTable("CarbonWheels"); - builder.Entity().ToTable("ChromeWheels"); - - builder.Entity().ToTable("Engines"); - builder.Entity().ToTable("GasolineEngines"); - builder.Entity().ToTable("DieselEngines"); - - builder.Entity().ToTable("GenericProperties"); - builder.Entity().ToTable("StringProperties"); - builder.Entity().ToTable("NumberProperties"); + builder.Entity() + .UseTptMappingStrategy(); + + builder.Entity() + .UseTptMappingStrategy(); + + builder.Entity() + .UseTptMappingStrategy(); + + builder.Entity() + .UseTptMappingStrategy(); base.OnModelCreating(builder); } diff --git a/test/SourceGeneratorTests/CompilationBuilder.cs b/test/SourceGeneratorTests/CompilationBuilder.cs index 6029b68eae..b4830e25f3 100644 --- a/test/SourceGeneratorTests/CompilationBuilder.cs +++ b/test/SourceGeneratorTests/CompilationBuilder.cs @@ -9,7 +9,13 @@ namespace SourceGeneratorTests; internal sealed class CompilationBuilder { - private static readonly CSharpCompilationOptions DefaultOptions = new(OutputKind.DynamicallyLinkedLibrary); + private static readonly CSharpCompilationOptions DefaultOptions = + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary).WithSpecificDiagnosticOptions(new Dictionary + { + // Suppress warning for version conflict on Microsoft.Extensions.Logging.Abstractions: + // JsonApiDotNetCore indirectly depends on v6 (via Entity Framework Core 6), whereas Entity Framework Core 7 depends on v7. + ["CS1701"] = ReportDiagnostic.Suppress + }); private readonly HashSet _syntaxTrees = new(); private readonly HashSet _references = new(); diff --git a/test/TestBuildingBlocks/DbContextExtensions.cs b/test/TestBuildingBlocks/DbContextExtensions.cs index 5bb3f81a14..8ce859f356 100644 --- a/test/TestBuildingBlocks/DbContextExtensions.cs +++ b/test/TestBuildingBlocks/DbContextExtensions.cs @@ -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 derivedTypes = entityType.GetConcreteDerivedTypesInclusive(); + await ClearTablesAsync(dbContext, derivedTypes.Select(derivedType => derivedType.ClrType).ToArray()); + } + else + { + await dbContext.Database.ExecuteSqlRawAsync($"delete from \"{tableName}\""); + } } } } diff --git a/test/TestBuildingBlocks/FakeLoggerFactory.cs b/test/TestBuildingBlocks/FakeLoggerFactory.cs index e490cdda7b..1a1ac6d402 100644 --- a/test/TestBuildingBlocks/FakeLoggerFactory.cs +++ b/test/TestBuildingBlocks/FakeLoggerFactory.cs @@ -59,6 +59,7 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except } public IDisposable BeginScope(TState state) + where TState : notnull { return NullScope.Instance; } diff --git a/test/TestBuildingBlocks/TestBuildingBlocks.csproj b/test/TestBuildingBlocks/TestBuildingBlocks.csproj index ce8c54ef3b..999498ebaa 100644 --- a/test/TestBuildingBlocks/TestBuildingBlocks.csproj +++ b/test/TestBuildingBlocks/TestBuildingBlocks.csproj @@ -10,7 +10,7 @@ - +