From 29ec1f6314a2e22540d6aa858ea9eb5233a2e5b2 Mon Sep 17 00:00:00 2001 From: Filip Grzonkowski Date: Sun, 1 Nov 2026 22:33:17 +0100 Subject: [PATCH 1/2] chore: build for EF Core 11 on .NET 11 alongside EF Core 10 on .NET 10 Both packages target net10.0 and net11.0. The net10.0 assets keep depending on EF Core 10 and Npgsql EF 10; the net11.0 assets depend on EF Core 11 and Npgsql EF 11. Npgsql EF 11 added IQuerySqlGeneratorFactory to the NpgsqlMigrationsSqlGenerator constructor, so the migrations SQL generator takes it on net11.0 only. Relates to #71 Co-Authored-By: Claude Opus 5.5 --- .github/workflows/release.yml | 6 ++++ .github/workflows/run-tests.yml | 6 ++++ .github/workflows/snapshots.yml | 6 ++++ .../CompatibilitySuppressions.xml | 16 ++++++++++ src/Eftdb.Design/Eftdb.Design.csproj | 7 ++-- src/Eftdb/Eftdb.csproj | 7 ++-- .../TimescaleDbMigrationsSqlGenerator.cs | 13 +++++++- tests/Eftdb.Tests/Eftdb.Tests.csproj | 14 ++++++-- ...uousAggregateExpressionIntegrationTests.cs | 4 +-- .../ContinuousAggregateIntegrationTests.cs | 32 +++++++++---------- ...ntinuousAggregatePolicyIntegrationTests.cs | 2 +- .../HypertableIntegrationTestsBase.cs | 4 +-- .../HypertableMigrateDataIntegrationTests.cs | 4 +-- .../Integration/TimeBucketIntegrationTests.cs | 6 ++-- 14 files changed, 93 insertions(+), 34 deletions(-) create mode 100644 src/Eftdb.Design/CompatibilitySuppressions.xml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 79a6b27..782b34d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -41,6 +41,12 @@ jobs: with: dotnet-version: "10.0.x" + - name: Setup .NET 11 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: "11.0.x" + dotnet-quality: "preview" + - name: Restore dependencies run: dotnet restore diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index bb77c1a..715df16 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -26,6 +26,12 @@ jobs: with: dotnet-version: '10.0.x' + - name: Setup .NET 11 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '11.0.x' + dotnet-quality: 'preview' + - name: Restore dependencies run: dotnet restore diff --git a/.github/workflows/snapshots.yml b/.github/workflows/snapshots.yml index 6313729..db5fedc 100644 --- a/.github/workflows/snapshots.yml +++ b/.github/workflows/snapshots.yml @@ -55,6 +55,12 @@ jobs: with: dotnet-version: "10.0.x" + - name: Setup .NET 11 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: "11.0.x" + dotnet-quality: "preview" + - name: Restore dependencies run: dotnet restore diff --git a/src/Eftdb.Design/CompatibilitySuppressions.xml b/src/Eftdb.Design/CompatibilitySuppressions.xml new file mode 100644 index 0000000..9d17b99 --- /dev/null +++ b/src/Eftdb.Design/CompatibilitySuppressions.xml @@ -0,0 +1,16 @@ + + + + + CP0002 + M:CmdScale.EntityFrameworkCore.TimescaleDB.Design.Generators.TimescaleCSharpModelGenerator.#ctor(Microsoft.EntityFrameworkCore.Scaffolding.ModelCodeGeneratorDependencies,Microsoft.EntityFrameworkCore.Design.Internal.IOperationReporter,System.IServiceProvider,Microsoft.EntityFrameworkCore.Design.IAnnotationCodeGenerator) + lib/net10.0/CmdScale.EntityFrameworkCore.TimescaleDB.Design.dll + lib/net11.0/CmdScale.EntityFrameworkCore.TimescaleDB.Design.dll + + + CP0002 + M:CmdScale.EntityFrameworkCore.TimescaleDB.Design.Generators.TimescaleDbAnnotationCodeGenerator.#ctor(Microsoft.EntityFrameworkCore.Design.AnnotationCodeGeneratorDependencies,Microsoft.EntityFrameworkCore.Design.Internal.IOperationReporter) + lib/net10.0/CmdScale.EntityFrameworkCore.TimescaleDB.Design.dll + lib/net11.0/CmdScale.EntityFrameworkCore.TimescaleDB.Design.dll + + \ No newline at end of file diff --git a/src/Eftdb.Design/Eftdb.Design.csproj b/src/Eftdb.Design/Eftdb.Design.csproj index 288e7ad..7d5aacf 100644 --- a/src/Eftdb.Design/Eftdb.Design.csproj +++ b/src/Eftdb.Design/Eftdb.Design.csproj @@ -1,6 +1,6 @@  - net10.0 + net10.0;net11.0 enable enable CmdScale.EntityFrameworkCore.TimescaleDB.Design @@ -23,9 +23,12 @@ True timescaledb;timescale;efcore;ef-core;entityframeworkcore;postgresql;postgres;time-series;timeseries;data;database;efcore-provider;provider;design;migrations;scaffolding;codegen;cli;tools - + + + + True diff --git a/src/Eftdb/Eftdb.csproj b/src/Eftdb/Eftdb.csproj index 50d09e3..7241f31 100644 --- a/src/Eftdb/Eftdb.csproj +++ b/src/Eftdb/Eftdb.csproj @@ -1,6 +1,6 @@  - net10.0 + net10.0;net11.0 enable enable CmdScale.EntityFrameworkCore.TimescaleDB @@ -41,7 +41,10 @@ - + + + + \ No newline at end of file diff --git a/src/Eftdb/TimescaleDbMigrationsSqlGenerator.cs b/src/Eftdb/TimescaleDbMigrationsSqlGenerator.cs index 2e27b1a..e95b7e6 100644 --- a/src/Eftdb/TimescaleDbMigrationsSqlGenerator.cs +++ b/src/Eftdb/TimescaleDbMigrationsSqlGenerator.cs @@ -6,6 +6,9 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; +#if NET11_0_OR_GREATER +using Microsoft.EntityFrameworkCore.Query; +#endif using Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure.Internal; using Npgsql.EntityFrameworkCore.PostgreSQL.Migrations; @@ -15,8 +18,16 @@ namespace CmdScale.EntityFrameworkCore.TimescaleDB internal class TimescaleDbMigrationsSqlGenerator( MigrationsSqlGeneratorDependencies dependencies, INpgsqlSingletonOptions npgsqlSingletonOptions, +#if NET11_0_OR_GREATER + IQuerySqlGeneratorFactory querySqlGeneratorFactory, +#endif TimescaleDbOptions? timescaleDbOptions = null, - IDiagnosticsLogger? migrationsLogger = null) : NpgsqlMigrationsSqlGenerator(dependencies, npgsqlSingletonOptions) + IDiagnosticsLogger? migrationsLogger = null) +#if NET11_0_OR_GREATER + : NpgsqlMigrationsSqlGenerator(dependencies, npgsqlSingletonOptions, querySqlGeneratorFactory) +#else + : NpgsqlMigrationsSqlGenerator(dependencies, npgsqlSingletonOptions) +#endif { private static readonly string SkipCommentPrefix = SqlBuilderHelper.SkipComment("Skipping Community Edition feature"); diff --git a/tests/Eftdb.Tests/Eftdb.Tests.csproj b/tests/Eftdb.Tests/Eftdb.Tests.csproj index 35caa6e..bd45646 100644 --- a/tests/Eftdb.Tests/Eftdb.Tests.csproj +++ b/tests/Eftdb.Tests/Eftdb.Tests.csproj @@ -2,7 +2,7 @@ Exe - net10.0 + net10.0;net11.0 enable enable CmdScale.EntityFrameworkCore.TimescaleDB.Tests @@ -18,14 +18,22 @@ - - + + + + + + + + + + diff --git a/tests/Eftdb.Tests/Integration/ContinuousAggregateExpressionIntegrationTests.cs b/tests/Eftdb.Tests/Integration/ContinuousAggregateExpressionIntegrationTests.cs index d718a15..19c55cf 100644 --- a/tests/Eftdb.Tests/Integration/ContinuousAggregateExpressionIntegrationTests.cs +++ b/tests/Eftdb.Tests/Integration/ContinuousAggregateExpressionIntegrationTests.cs @@ -89,7 +89,7 @@ public async Task Should_Group_And_Aggregate_By_Expressions() await using ExpressionContext context = new(_connectionString!); await CreateDatabaseViaMigrationAsync(context); DateTime day = new(2025, 1, 6, 10, 0, 0, DateTimeKind.Utc); - await context.Database.ExecuteSqlInterpolatedAsync($""" + await context.Database.ExecuteSqlAsync($""" INSERT INTO expression_events (occurred_at, actor_id, impersonated_actor_id, action) VALUES ({day}, {"a"}, NULL, {(short)1}), ({day}, {"a"}, NULL, {(short)1}), ({day}, {"b"}, {"p"}, {(short)4}) """, TestContext.Current.CancellationToken); @@ -213,7 +213,7 @@ public async Task Should_Rank_With_Sketches_And_Roll_Them_Up() await CreateDatabaseViaMigrationAsync(context); DateTime monday = new(2025, 1, 6, 10, 0, 0, DateTimeKind.Utc); DateTime tuesday = monday.AddDays(1); - await context.Database.ExecuteSqlInterpolatedAsync($""" + await context.Database.ExecuteSqlAsync($""" INSERT INTO sketch_events (occurred_at, actor_id) VALUES ({monday}, {"busy"}), ({monday}, {"busy"}), ({tuesday}, {"busy"}), ({tuesday}, {"quiet"}) """, TestContext.Current.CancellationToken); diff --git a/tests/Eftdb.Tests/Integration/ContinuousAggregateIntegrationTests.cs b/tests/Eftdb.Tests/Integration/ContinuousAggregateIntegrationTests.cs index 2e27c53..0fc9d25 100644 --- a/tests/Eftdb.Tests/Integration/ContinuousAggregateIntegrationTests.cs +++ b/tests/Eftdb.Tests/Integration/ContinuousAggregateIntegrationTests.cs @@ -101,7 +101,7 @@ public async Task Should_Create_ContinuousAggregate_With_BasicAggregates() await using BasicAggregatesContext context = new(_connectionString!); await CreateDatabaseViaMigrationAsync(context); - await context.Database.ExecuteSqlInterpolatedAsync($@" + await context.Database.ExecuteSqlAsync($@" INSERT INTO ""Trades"" (""Timestamp"", ""Ticker"", ""Price"", ""Size"", ""Exchange"") VALUES ({new DateTime(2025, 1, 6, 10, 0, 0, DateTimeKind.Utc)}, {"AAPL"}, {150.50m}, {100}, {"NYSE"}), @@ -183,7 +183,7 @@ public async Task Should_Create_ContinuousAggregate_With_FirstAndLast_Functions( await using FirstLastContext context = new(_connectionString!); await CreateDatabaseViaMigrationAsync(context); - await context.Database.ExecuteSqlInterpolatedAsync($@" + await context.Database.ExecuteSqlAsync($@" INSERT INTO ""Trades"" (""Timestamp"", ""Ticker"", ""Price"", ""Size"", ""Exchange"") VALUES ({new DateTime(2025, 1, 6, 10, 0, 0, DateTimeKind.Utc)}, {"AAPL"}, {100.00m}, {100}, {"NYSE"}), @@ -260,7 +260,7 @@ public async Task Should_Create_ContinuousAggregate_With_GroupByColumns() await using GroupByContext context = new(_connectionString!); await CreateDatabaseViaMigrationAsync(context); - await context.Database.ExecuteSqlInterpolatedAsync($@" + await context.Database.ExecuteSqlAsync($@" INSERT INTO ""Trades"" (""Timestamp"", ""Ticker"", ""Price"", ""Size"", ""Exchange"") VALUES ({new DateTime(2025, 1, 6, 10, 0, 0, DateTimeKind.Utc)}, {"AAPL"}, {100.00m}, {100}, {"NYSE"}), @@ -341,7 +341,7 @@ public async Task Should_Create_ContinuousAggregate_With_WhereClause() await using WhereClauseContext context = new(_connectionString!); await CreateDatabaseViaMigrationAsync(context); - await context.Database.ExecuteSqlInterpolatedAsync($@" + await context.Database.ExecuteSqlAsync($@" INSERT INTO ""Trades"" (""Timestamp"", ""Ticker"", ""Price"", ""Size"", ""Exchange"") VALUES ({new DateTime(2025, 1, 6, 10, 0, 0, DateTimeKind.Utc)}, {"AAPL"}, {100.00m}, {100}, {"NYSE"}), @@ -415,7 +415,7 @@ public async Task Should_Create_ContinuousAggregate_WithNoData_Option() await using WithNoDataContext context = new(_connectionString!); await CreateDatabaseViaMigrationAsync(context); - await context.Database.ExecuteSqlInterpolatedAsync($@" + await context.Database.ExecuteSqlAsync($@" INSERT INTO ""Trades"" (""Timestamp"", ""Ticker"", ""Price"", ""Size"", ""Exchange"") VALUES ({new DateTime(2025, 1, 6, 10, 0, 0, DateTimeKind.Utc)}, {"AAPL"}, {100.00m}, {100}, {"NYSE"})", TestContext.Current.CancellationToken); @@ -488,7 +488,7 @@ public async Task Should_Create_ContinuousAggregate_With_CustomChunkInterval() await using CustomChunkIntervalContext context = new(_connectionString!); await CreateDatabaseViaMigrationAsync(context); - await context.Database.ExecuteSqlInterpolatedAsync($@" + await context.Database.ExecuteSqlAsync($@" INSERT INTO ""Trades"" (""Timestamp"", ""Ticker"", ""Price"", ""Size"", ""Exchange"") VALUES ({new DateTime(2025, 1, 6, 10, 0, 0, DateTimeKind.Utc)}, {"AAPL"}, {150.50m}, {100}, {"NYSE"}), @@ -564,7 +564,7 @@ public async Task Should_Create_ContinuousAggregate_With_CreateGroupIndexes() await using CreateGroupIndexesContext context = new(_connectionString!); await CreateDatabaseViaMigrationAsync(context); - await context.Database.ExecuteSqlInterpolatedAsync($@" + await context.Database.ExecuteSqlAsync($@" INSERT INTO ""Trades"" (""Timestamp"", ""Ticker"", ""Price"", ""Size"", ""Exchange"") VALUES ({new DateTime(2025, 1, 6, 10, 0, 0, DateTimeKind.Utc)}, {"AAPL"}, {150.50m}, {100}, {"NYSE"}), @@ -637,7 +637,7 @@ public async Task Should_Create_ContinuousAggregate_With_MaterializedOnly_False( await using MaterializedOnlyFalseContext context = new(_connectionString!); await CreateDatabaseViaMigrationAsync(context); - await context.Database.ExecuteSqlInterpolatedAsync($@" + await context.Database.ExecuteSqlAsync($@" INSERT INTO ""Trades"" (""Timestamp"", ""Ticker"", ""Price"", ""Size"", ""Exchange"") VALUES ({new DateTime(2025, 1, 6, 10, 0, 0, DateTimeKind.Utc)}, {"AAPL"}, {100.00m}, {100}, {"NYSE"})", TestContext.Current.CancellationToken); @@ -737,7 +737,7 @@ public async Task Should_Alter_ContinuousAggregate_ChunkInterval() await using AlterChunkIntervalInitialContext context1 = new(_connectionString!); await context1.Database.EnsureCreatedAsync(TestContext.Current.CancellationToken); - await context1.Database.ExecuteSqlInterpolatedAsync($@" + await context1.Database.ExecuteSqlAsync($@" INSERT INTO ""Trades"" (""Timestamp"", ""Ticker"", ""Price"", ""Size"", ""Exchange"") VALUES ({new DateTime(2025, 1, 6, 10, 0, 0, DateTimeKind.Utc)}, {"AAPL"}, {150.50m}, {100}, {"NYSE"}), @@ -820,7 +820,7 @@ public async Task Should_Alter_ContinuousAggregate_MaterializedOnly() await using AlterMaterializedOnlyContext context = new(_connectionString!); await CreateDatabaseViaMigrationAsync(context); - await context.Database.ExecuteSqlInterpolatedAsync($@" + await context.Database.ExecuteSqlAsync($@" INSERT INTO ""Trades"" (""Timestamp"", ""Ticker"", ""Price"", ""Size"", ""Exchange"") VALUES ({new DateTime(2025, 1, 6, 10, 0, 0, DateTimeKind.Utc)}, {"AAPL"}, {150.50m}, {100}, {"NYSE"}), @@ -966,7 +966,7 @@ public async Task Should_Drop_ContinuousAggregate_Successfully() await using DropContext context = new(_connectionString!); await CreateDatabaseViaMigrationAsync(context); - await context.Database.ExecuteSqlInterpolatedAsync($@" + await context.Database.ExecuteSqlAsync($@" INSERT INTO ""Trades"" (""Timestamp"", ""Ticker"", ""Price"", ""Size"", ""Exchange"") VALUES ({new DateTime(2025, 1, 6, 10, 0, 0, DateTimeKind.Utc)}, {"AAPL"}, {150.50m}, {100}, {"NYSE"}), @@ -1045,7 +1045,7 @@ public async Task Should_Generate_Correct_SQL_For_ContinuousAggregate() await using SqlGenerationContext context = new(_connectionString!); await CreateDatabaseViaMigrationAsync(context); - await context.Database.ExecuteSqlInterpolatedAsync($@" + await context.Database.ExecuteSqlAsync($@" INSERT INTO ""Trades"" (""Timestamp"", ""Ticker"", ""Price"", ""Size"", ""Exchange"") VALUES ({new DateTime(2025, 1, 6, 10, 0, 0, DateTimeKind.Utc)}, {"AAPL"}, {150.50m}, {100}, {"NYSE"}), @@ -1120,7 +1120,7 @@ public async Task Should_Handle_SnakeCase_Naming_Convention() await using SnakeCaseContext context = new(_connectionString!); await CreateDatabaseViaMigrationAsync(context); - await context.Database.ExecuteSqlInterpolatedAsync($@" + await context.Database.ExecuteSqlAsync($@" INSERT INTO trades (timestamp, ticker, price, size, exchange) VALUES ({new DateTime(2025, 1, 6, 10, 0, 0, DateTimeKind.Utc)}, {"AAPL"}, {100.00m}, {100}, {"NYSE"})", TestContext.Current.CancellationToken); @@ -1189,7 +1189,7 @@ public async Task Should_Create_ContinuousAggregate_With_CountStar_And_Verify_Co await using CountStarIntegrationContext context = new(_connectionString!); await CreateDatabaseViaMigrationAsync(context); - await context.Database.ExecuteSqlInterpolatedAsync($@" + await context.Database.ExecuteSqlAsync($@" INSERT INTO count_star_events (""Timestamp"", ""Category"", ""Value"") VALUES ({new DateTime(2025, 1, 6, 10, 0, 0, DateTimeKind.Utc)}, {"sports"}, {1.0m}), @@ -1462,7 +1462,7 @@ JOIN _timescaledb_catalog.continuous_agg parent Assert.Contains("hier_chain_1d<-hier_chain_4h", parentLinks); // Act - await context.Database.ExecuteSqlInterpolatedAsync($@" + await context.Database.ExecuteSqlAsync($@" INSERT INTO hier_chain_raw (""Timestamp"", ""Value"") VALUES ({new DateTime(2025, 1, 6, 10, 0, 0, DateTimeKind.Utc)}, {10.0}), @@ -1594,7 +1594,7 @@ FROM timescaledb_information.jobs j Assert.Contains("hier_combo_daily", policyTargets); // Act - await context.Database.ExecuteSqlInterpolatedAsync($@" + await context.Database.ExecuteSqlAsync($@" INSERT INTO hier_combo_readings (""Timestamp"", ""MeterId"", ""PowerKw"") VALUES ({new DateTime(2025, 1, 6, 10, 0, 0, DateTimeKind.Utc)}, {"meter-a"}, {1.0}), diff --git a/tests/Eftdb.Tests/Integration/ContinuousAggregatePolicyIntegrationTests.cs b/tests/Eftdb.Tests/Integration/ContinuousAggregatePolicyIntegrationTests.cs index 1b6d2fe..0978e56 100644 --- a/tests/Eftdb.Tests/Integration/ContinuousAggregatePolicyIntegrationTests.cs +++ b/tests/Eftdb.Tests/Integration/ContinuousAggregatePolicyIntegrationTests.cs @@ -515,7 +515,7 @@ public async Task Should_Execute_Migration_Successfully() await CreateDatabaseViaMigrationAsync(context); // Assert - await context.Database.ExecuteSqlInterpolatedAsync($@" + await context.Database.ExecuteSqlAsync($@" INSERT INTO ""Metrics"" (""Timestamp"", ""Value"") VALUES ({new DateTime(2025, 1, 1, 10, 0, 0, DateTimeKind.Utc)}, {100.5}) ", TestContext.Current.CancellationToken); diff --git a/tests/Eftdb.Tests/Integration/HypertableIntegrationTestsBase.cs b/tests/Eftdb.Tests/Integration/HypertableIntegrationTestsBase.cs index 5a8b83b..d49f261 100644 --- a/tests/Eftdb.Tests/Integration/HypertableIntegrationTestsBase.cs +++ b/tests/Eftdb.Tests/Integration/HypertableIntegrationTestsBase.cs @@ -151,7 +151,7 @@ public async Task Should_Create_Minimal_Hypertable() DateTime timestamp = new(2025, 1, 6, 10, 0, 0, DateTimeKind.Utc); double value = 100.5; - await context.Database.ExecuteSqlInterpolatedAsync( + await context.Database.ExecuteSqlAsync( $"INSERT INTO \"Metrics\" (\"Timestamp\", \"Value\") VALUES ({timestamp}, {value})", TestContext.Current.CancellationToken); bool isHypertable = await HypertableProbe.IsHypertableAsync(context, "Metrics"); @@ -464,7 +464,7 @@ public async Task Should_Insert_And_Query_Data_From_Hypertable() await using DataOperationsContext context = new(_connectionString!); await CreateDatabaseViaMigrationAsync(context); - await context.Database.ExecuteSqlInterpolatedAsync($@" + await context.Database.ExecuteSqlAsync($@" INSERT INTO ""IoTData"" (""Timestamp"", ""DeviceId"", ""Temperature"", ""Humidity"") VALUES ({new DateTime(2025, 1, 1, 10, 0, 0, DateTimeKind.Utc)}, {"device_1"}, {20.5}, {45.0}), diff --git a/tests/Eftdb.Tests/Integration/HypertableMigrateDataIntegrationTests.cs b/tests/Eftdb.Tests/Integration/HypertableMigrateDataIntegrationTests.cs index 0328239..7ae84fd 100644 --- a/tests/Eftdb.Tests/Integration/HypertableMigrateDataIntegrationTests.cs +++ b/tests/Eftdb.Tests/Integration/HypertableMigrateDataIntegrationTests.cs @@ -300,7 +300,7 @@ public async Task Should_Migrate_Existing_Data_When_Converting_To_Hypertable() await using InitialRegularTableContext initialContext = new(_connectionString!); await CreateDatabaseViaMigrationAsync(initialContext); - await initialContext.Database.ExecuteSqlInterpolatedAsync($@" + await initialContext.Database.ExecuteSqlAsync($@" INSERT INTO ""SensorDataMigration"" (""Timestamp"", ""DeviceId"", ""Temperature"") VALUES ({new DateTime(2025, 1, 1, 10, 0, 0, DateTimeKind.Utc)}, {"device_1"}, {20.5}), @@ -382,7 +382,7 @@ public async Task Should_Apply_MigrateData_False_When_Converting_To_Hypertable() await using InitialRegularTableMigrateDataFalseContext initialContext = new(_connectionString!); await CreateDatabaseViaMigrationAsync(initialContext); - await initialContext.Database.ExecuteSqlInterpolatedAsync($@" + await initialContext.Database.ExecuteSqlAsync($@" INSERT INTO ""SensorDataNoMigration"" (""Timestamp"", ""DeviceId"", ""Temperature"") VALUES ({new DateTime(2025, 1, 1, 10, 0, 0, DateTimeKind.Utc)}, {"device_1"}, {20.5})", TestContext.Current.CancellationToken); diff --git a/tests/Eftdb.Tests/Integration/TimeBucketIntegrationTests.cs b/tests/Eftdb.Tests/Integration/TimeBucketIntegrationTests.cs index 1d74d70..0cba31f 100644 --- a/tests/Eftdb.Tests/Integration/TimeBucketIntegrationTests.cs +++ b/tests/Eftdb.Tests/Integration/TimeBucketIntegrationTests.cs @@ -68,7 +68,7 @@ public async Task Should_Translate_TimeBucket_In_Select() for (int i = 0; i < 5; i++) { DateTime ts = baseTime.AddMinutes(i); - await context.Database.ExecuteSqlInterpolatedAsync( + await context.Database.ExecuteSqlAsync( $"INSERT INTO \"tb_select_metrics\" (\"Timestamp\", \"Value\") VALUES ({ts}, {(double)(i * 10)})", TestContext.Current.CancellationToken); } @@ -122,7 +122,7 @@ public async Task Should_Translate_TimeBucket_In_GroupBy() for (int i = 0; i < 12; i++) { DateTime ts = baseTime.AddMinutes(i); - await context.Database.ExecuteSqlInterpolatedAsync( + await context.Database.ExecuteSqlAsync( $"INSERT INTO \"tb_groupby_metrics\" (\"Timestamp\", \"Value\") VALUES ({ts}, {(double)(i + 1)})", TestContext.Current.CancellationToken); } @@ -189,7 +189,7 @@ public async Task Should_Translate_TimeBucket_With_Integer_Arguments() for (int i = 0; i < 20; i++) { - await context.Database.ExecuteSqlInterpolatedAsync( + await context.Database.ExecuteSqlAsync( $"INSERT INTO \"tb_int_metrics\" (\"Id\", \"SequenceNumber\", \"Value\") VALUES ({i + 1}, {i}, {(double)(i * 10)})", TestContext.Current.CancellationToken); } From 4425f5b57fd22b257ca9a60495c9917cfe435d39 Mon Sep 17 00:00:00 2001 From: Filip Grzonkowski Date: Mon, 2 Nov 2026 10:20:46 +0100 Subject: [PATCH 2/2] ci: pass an absolute --project path to dotnet test With the .NET 11 SDK installed next to 10.0.x, the build uses SDK 11.0.100-rc.3, which resolves a relative --project path a second time against the project directory for multi-targeted projects. The test step then fails with "Could not find a part of the path .../tests/Eftdb.Tests/tests/Eftdb.Tests/Eftdb.Tests.csproj". Passing the path under github.workspace avoids it. The working directory and the other test arguments stay unchanged. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/run-tests.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 715df16..95cc99a 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -38,8 +38,10 @@ jobs: - name: Build project run: dotnet build --no-restore + # Absolute project path: the .NET 11 SDK resolves a relative --project against the + # project directory again for multi-targeted projects (tests/Eftdb.Tests/tests/Eftdb.Tests/...) - name: Run unit and integration tests with coverage - run: dotnet test --no-build --project tests/Eftdb.Tests -- --coverage --coverage-output-format cobertura --coverage-settings tests/coverage.config --results-directory ./coverage + run: dotnet test --no-build --project ${{ github.workspace }}/tests/Eftdb.Tests/Eftdb.Tests.csproj -- --coverage --coverage-output-format cobertura --coverage-settings tests/coverage.config --results-directory ./coverage - name: Run functional tests working-directory: tests/Eftdb.FunctionalTests