diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index b22b0193..1de57440 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -5,7 +5,8 @@ "ghcr.io/devcontainers/features/dotnet:2": { "additionalVersions": [ "8.0", - "9.0" + "9.0", + "11.0" ] }, "ghcr.io/devcontainers/features/node:1": {}, diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f1913a7e..e5f1ad59 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,6 +31,15 @@ jobs: 9.0.x 10.0.x + # Separate step: dotnet-quality applies to every wildcard version in a + # step, and the 8/9/10 SDKs above must keep resolving to GA releases. + # Fold into the block above (and drop the quality flag) at .NET 11 GA. + - name: Setup .NET 11 SDK (RC) + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 11.0.x + dotnet-quality: preview + - name: Cache NuGet packages uses: actions/cache@v4 with: @@ -51,13 +60,15 @@ jobs: # Docker or pay the container startup cost on every PR. run: | set -e + # --project must be absolute: the .NET 11 RC SDK's dotnet test resolves + # relative --project paths against the project directory, doubling them. for proj in \ tests/ExpressiveSharp.Tests \ tests/ExpressiveSharp.IntegrationTests \ tests/ExpressiveSharp.Generator.Tests \ tests/ExpressiveSharp.EntityFrameworkCore.IntegrationTests; do dotnet test --no-build -c Release \ - --project "$proj" \ + --project "$GITHUB_WORKSPACE/$proj" \ --results-directory ./test-results \ -- \ --report-trx --report-trx-filename "$(basename "$proj").trx" \ @@ -135,6 +146,15 @@ jobs: 9.0.x 10.0.x + # Separate step: dotnet-quality applies to every wildcard version in a + # step, and the 8/9/10 SDKs above must keep resolving to GA releases. + # Fold into the block above (and drop the quality flag) at .NET 11 GA. + - name: Setup .NET 11 SDK (RC) + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 11.0.x + dotnet-quality: preview + - name: Cache NuGet packages uses: actions/cache@v4 with: @@ -163,10 +183,10 @@ jobs: # connects to the gateway-advertised endpoint, which must # match the host-side port), so only one emulator can run # at a time. Run TFMs sequentially. - for tfm in net8.0 net9.0 net10.0; do + for tfm in net8.0 net9.0 net10.0 net11.0; do echo "::group::Cosmos tests ($tfm)" dotnet test --no-build -c Release \ - --project tests/ExpressiveSharp.EntityFrameworkCore.IntegrationTests \ + --project "$GITHUB_WORKSPACE/tests/ExpressiveSharp.EntityFrameworkCore.IntegrationTests" \ -p:TestDatabase=${{ matrix.database }} \ -f "$tfm" \ --results-directory ./test-results \ @@ -176,7 +196,7 @@ jobs: done else dotnet test --no-build -c Release \ - --project tests/ExpressiveSharp.EntityFrameworkCore.IntegrationTests \ + --project "$GITHUB_WORKSPACE/tests/ExpressiveSharp.EntityFrameworkCore.IntegrationTests" \ -p:TestDatabase=${{ matrix.database }} \ --results-directory ./test-results \ -- \ @@ -220,6 +240,15 @@ jobs: 9.0.x 10.0.x + # Separate step: dotnet-quality applies to every wildcard version in a + # step, and the 8/9/10 SDKs above must keep resolving to GA releases. + # Fold into the block above (and drop the quality flag) at .NET 11 GA. + - name: Setup .NET 11 SDK (RC) + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 11.0.x + dotnet-quality: preview + - name: Cache NuGet packages uses: actions/cache@v4 with: @@ -242,7 +271,7 @@ jobs: - name: Test run: >- dotnet test --no-build -c Release - --project tests/ExpressiveSharp.MongoDB.IntegrationTests + --project "$GITHUB_WORKSPACE/tests/ExpressiveSharp.MongoDB.IntegrationTests" --results-directory ./test-results -- --report-trx --report-trx-filename results.trx diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 520d02f0..ac806b98 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -35,6 +35,15 @@ jobs: 9.0.x 10.0.x + # Separate step: dotnet-quality applies to every wildcard version in a + # step, and the 8/9/10 SDKs above must keep resolving to GA releases. + # Fold into the block above (and drop the quality flag) at .NET 11 GA. + - name: Setup .NET 11 SDK (RC) + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 11.0.x + dotnet-quality: preview + - name: Cache NuGet packages uses: actions/cache@v4 with: diff --git a/CLAUDE.md b/CLAUDE.md index 1919a7e7..d2f87010 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -35,7 +35,7 @@ dotnet run -c Release --project benchmarks/ExpressiveSharp.Benchmarks/Expressive dotnet run -c Release --project benchmarks/ExpressiveSharp.Benchmarks/ExpressiveSharp.Benchmarks.csproj -- --filter "*GeneratorBenchmarks*" ``` -CI targets both .NET 8.0 and .NET 10.0 SDKs. +CI targets the .NET 8.0, 9.0, 10.0, and 11.0 (RC) SDKs. ## Architecture @@ -67,12 +67,12 @@ CI targets both .NET 8.0 and .NET 10.0 SDKs. ### Project Dependencies ``` -ExpressiveSharp.Abstractions (attributes + source generator, net8.0;net10.0) +ExpressiveSharp.Abstractions (attributes + source generator, net8.0;net9.0;net10.0;net11.0) └── no external deps Provides: [Expressive], [ExpressiveFor], [ExpressiveForConstructor], [PolyfillTarget], IExpressionTreeTransformer, source generator + code fixers (as analyzers) -ExpressiveSharp (core runtime, net8.0;net10.0) +ExpressiveSharp (core runtime, net8.0;net9.0;net10.0;net11.0) └── ExpressiveSharp.Abstractions Provides: ExpressiveResolver, ExpressiveReplacer, expression transformers, IExpressiveQueryable, ExpressionPolyfill, .ExpandExpressives(), .AsExpressive() @@ -80,20 +80,20 @@ ExpressiveSharp (core runtime, net8.0;net10.0) ExpressiveSharp.Generator (source generator, netstandard2.0) └── Microsoft.CodeAnalysis.CSharp 5.0.0 -ExpressiveSharp.MongoDB (net8.0;net10.0) +ExpressiveSharp.MongoDB (net8.0;net9.0;net10.0;net11.0) ├── ExpressiveSharp ├── MongoDB.Driver 3.4.0 └── Provides: IRewritableMongoQueryable, ExpressiveMongoCollection, ExpressiveMongoQueryProvider (decorating IQueryProvider/IMongoQueryProvider), async lambda stubs with [PolyfillTarget(typeof(MongoQueryable))] -ExpressiveSharp.EntityFrameworkCore (net8.0;net10.0) +ExpressiveSharp.EntityFrameworkCore (net8.0;net9.0;net10.0;net11.0) ├── ExpressiveSharp - ├── EF Core 8.0.25 / 10.0.0 + ├── EF Core 8.0.25 / 9.0.0 / 10.0.0 / 11.0.0-rc.1 (per-TFM VersionOverride) └── Provides: ExpressiveDbSet, IIncludableExpressiveQueryable, chain-continuity stubs, async lambda stubs with [PolyfillTarget] -ExpressiveSharp.EntityFrameworkCore.RelationalExtensions.Abstractions (net8.0;net10.0) +ExpressiveSharp.EntityFrameworkCore.RelationalExtensions.Abstractions (net8.0;net9.0;net10.0 — no net11.0, see below) └── no external deps Provides: Pure marker types for window functions — no EF Core dependency: WindowFunction (ranking: ROW_NUMBER, RANK, DENSE_RANK, NTILE, PERCENT_RANK, CUME_DIST; @@ -101,16 +101,22 @@ ExpressiveSharp.EntityFrameworkCore.RelationalExtensions.Abstractions (net8.0;ne LAST_VALUE, NTH_VALUE), Window, OrderedWindowDefinition, PartitionedWindowDefinition, FramedWindowDefinition, WindowFrameBound -ExpressiveSharp.EntityFrameworkCore.RelationalExtensions (net8.0;net10.0) +ExpressiveSharp.EntityFrameworkCore.RelationalExtensions (net8.0;net9.0;net10.0 — no net11.0, see below) ├── ExpressiveSharp.EntityFrameworkCore ├── ExpressiveSharp.EntityFrameworkCore.RelationalExtensions.Abstractions - ├── EF Core Relational 8.0.25 / 10.0.0 + ├── EF Core Relational 8.0.25 / 9.0.0 / 10.0.0 (per-TFM VersionOverride) └── Provides: Window function SQL translation (ranking, aggregate with ROWS/RANGE frame clauses, navigation with LAG/LEAD/FIRST_VALUE/LAST_VALUE/NTH_VALUE), indexed Select, activated via UseExpressives(o => o.UseRelationalExtensions()). Translators: WindowFunctionMethodCallTranslator, WindowSpecMethodCallTranslator, WindowFrameBoundMemberTranslator (IMemberTranslatorPlugin for property getters). Note: NTH_VALUE is not supported on SQL Server. + EF Core 11 is unsupported: both RelationalExtensions packages deliberately do + not target net11.0 — EF 11 removed the QuerySqlGenerator VisitChildren fallback + that WindowFunctionSqlExpression's self-rendering relied on, with no replacement + extension point (dotnet/efcore#37533; tracked in dotnet/efcore#38977). Test + projects gate on a RelationalExtensionsSupported msbuild property. Add the TFM + back (and drop those gates) once EF provides a hook. ExpressiveSharp.EntityFrameworkCore.CodeFixers (Roslyn analyzer, netstandard2.0) └── Microsoft.CodeAnalysis.CSharp.Workspaces 4.12.0 @@ -145,7 +151,7 @@ Snapshot tests use `GeneratorTestBase.RunExpressiveGenerator()` to compile via R - `TreatWarningsAsErrors: true` — all warnings are errors - `Nullable: enable` — full nullable reference types -- C# 12.0 on net8.0, C# 14.0 on net10.0 +- C# 14.0 on all TFMs (net8.0–net11.0; `LangVersion` is set globally in `Directory.Build.props`) - Allman brace style, 4-space indentation, `var` preferred - Instance fields: `_camelCase` - Expression-bodied members preferred for methods/properties diff --git a/Directory.Build.props b/Directory.Build.props index dbae29cc..3f10bb04 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,6 +1,6 @@ - net8.0;net9.0;net10.0 + net8.0;net9.0;net10.0;net11.0 true 14.0 enable diff --git a/Directory.Packages.props b/Directory.Packages.props index 061e9371..28e8cae9 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -24,6 +24,7 @@ + diff --git a/README.md b/README.md index ac253a0c..6f07c7e0 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ Mark computed properties and methods with `[Expressive]` to generate companion e | External member mapping | `[ExpressiveFor]` for BCL/third-party members | | Tuples, index/range, `with`, collection expressions | And more modern C# syntax | | Expression transformers | Built-in + custom `IExpressionTreeTransformer` pipeline | -| SQL window functions | ROW_NUMBER, RANK, DENSE_RANK, NTILE, PERCENT_RANK, CUME_DIST, SUM/AVG/COUNT/MIN/MAX OVER, LAG/LEAD, FIRST_VALUE/LAST_VALUE/NTH_VALUE with ROWS/RANGE frames | +| SQL window functions | ROW_NUMBER, RANK, DENSE_RANK, NTILE, PERCENT_RANK, CUME_DIST, SUM/AVG/COUNT/MIN/MAX OVER, LAG/LEAD, FIRST_VALUE/LAST_VALUE/NTH_VALUE with ROWS/RANGE frames (EF Core 8–10) | | Hot reload | Compatible with `dotnet watch` — edits to `[Expressive]` bodies propagate to generated expression trees | See the [full documentation](https://efnext.github.io/ExpressiveSharp/guide/introduction) for detailed usage, [reference](https://efnext.github.io/ExpressiveSharp/reference/expressive-attribute), and [recipes](https://efnext.github.io/ExpressiveSharp/recipes/computed-properties). diff --git a/docs/advanced/limitations.md b/docs/advanced/limitations.md index 9be275ff..e22164b8 100644 --- a/docs/advanced/limitations.md +++ b/docs/advanced/limitations.md @@ -227,4 +227,8 @@ The `ExpressiveSharp.EntityFrameworkCore.RelationalExtensions` package implement Non-relational providers (Cosmos DB, in-memory) are not supported for window functions. +### EF Core 11 is not supported + +The `RelationalExtensions` packages support EF Core 8, 9, and 10 but do not ship a `net11.0` target: EF Core 11 removed the `QuerySqlGenerator` fallback that renders third-party SQL expressions ([dotnet/efcore#37533](https://github.com/dotnet/efcore/pull/37533)), with no replacement extension point. Support returns once EF Core provides one — tracked in [dotnet/efcore#38977](https://github.com/dotnet/efcore/issues/38977). Applications on .NET 11 that need window functions should stay on EF Core 10, which runs fine on the .NET 11 runtime. Note that NuGet will not block installing the package in a `net11.0` project — it silently falls back to the `net10.0` build, and window functions then fail at runtime with EF Core 11's `Unhandled expression … in 'QuerySqlGenerator'` error. + EF Core also tracks native window function support in [dotnet/efcore#12747](https://github.com/dotnet/efcore/issues/12747); see the [window functions guide](../guide/window-functions#forward-compatibility) for forward-compatibility notes. diff --git a/docs/advanced/testing-strategy.md b/docs/advanced/testing-strategy.md index cc0af5f5..eb4d1066 100644 --- a/docs/advanced/testing-strategy.md +++ b/docs/advanced/testing-strategy.md @@ -103,7 +103,7 @@ dotnet test --filter "FullyQualifiedName~MyTestName" dotnet test -f net8.0 -c Release ``` -CI targets both .NET 8.0 and .NET 10.0 SDKs. +CI targets the .NET 8.0, 9.0, 10.0, and 11.0 SDKs. ## Performance Benchmarks diff --git a/docs/guide/integrations/ef-core.md b/docs/guide/integrations/ef-core.md index 5af1ca93..fc99f9d9 100644 --- a/docs/guide/integrations/ef-core.md +++ b/docs/guide/integrations/ef-core.md @@ -149,6 +149,10 @@ Supported chain-preserving operations: With the `ExpressiveSharp.EntityFrameworkCore.RelationalExtensions` package, you can use modern C# syntax inside `ExecuteUpdate` / `ExecuteUpdateAsync`: +::: warning +The `RelationalExtensions` package supports EF Core 8–10 only; it does not ship a `net11.0` target until EF Core 11 restores an extension point for third-party SQL expressions ([dotnet/efcore#38977](https://github.com/dotnet/efcore/issues/38977)). See the [window functions guide](../window-functions) for details. +::: + ```csharp // Requires: .UseExpressives(o => o.UseRelationalExtensions()) ctx.Orders diff --git a/docs/guide/quickstart.md b/docs/guide/quickstart.md index 0b9947ae..6059c177 100644 --- a/docs/guide/quickstart.md +++ b/docs/guide/quickstart.md @@ -4,7 +4,7 @@ This guide walks you through a complete end-to-end example — from installing t ## Prerequisites -- .NET 8 SDK or later (.NET 10 also supported) +- .NET 8 SDK or later (.NET 9, 10, and 11 also supported) - A LINQ provider. ExpressiveSharp integrates with **EF Core**, **MongoDB**, or **any `IQueryable`**. ## Step 1 — Install the Packages @@ -39,7 +39,7 @@ dotnet add package ExpressiveSharp.MongoDB | `ExpressiveSharp.Abstractions` | Lightweight — `[Expressive]` attribute, `[ExpressiveFor]`, `IExpressionTreeTransformer`, source generator only (no runtime services) | | `ExpressiveSharp.EntityFrameworkCore` | EF Core integration — `UseExpressives()`, `ExpressiveDbSet`, Include/ThenInclude, async methods, analyzers and code fixes | | `ExpressiveSharp.MongoDB` | MongoDB integration — `.AsExpressive()` on `IMongoCollection`, MQL aggregation translation | -| `ExpressiveSharp.EntityFrameworkCore.RelationalExtensions` | SQL window functions — ranking (ROW_NUMBER, RANK, DENSE_RANK, NTILE, PERCENT_RANK, CUME_DIST), aggregate (SUM, AVG, COUNT, MIN, MAX), and navigation (LAG, LEAD, FIRST_VALUE, LAST_VALUE, NTH_VALUE) with PARTITION BY / ORDER BY / ROWS\|RANGE frame support, plus indexed Select. | +| `ExpressiveSharp.EntityFrameworkCore.RelationalExtensions` | SQL window functions (EF Core 8–10; [EF Core 11 pending](https://github.com/dotnet/efcore/issues/38977)) — ranking (ROW_NUMBER, RANK, DENSE_RANK, NTILE, PERCENT_RANK, CUME_DIST), aggregate (SUM, AVG, COUNT, MIN, MAX), and navigation (LAG, LEAD, FIRST_VALUE, LAST_VALUE, NTH_VALUE) with PARTITION BY / ORDER BY / ROWS\|RANGE frame support, plus indexed Select. | ## Step 2 — Define Your Entities diff --git a/docs/guide/window-functions.md b/docs/guide/window-functions.md index 392e318b..96d18d45 100644 --- a/docs/guide/window-functions.md +++ b/docs/guide/window-functions.md @@ -2,6 +2,10 @@ ExpressiveSharp provides SQL window function support through the `ExpressiveSharp.EntityFrameworkCore.RelationalExtensions` package. This enables ranking (ROW_NUMBER, RANK, DENSE_RANK, NTILE, PERCENT_RANK, CUME_DIST), aggregate (SUM, AVG, COUNT, MIN, MAX), and navigation (LAG, LEAD, FIRST_VALUE, LAST_VALUE, NTH_VALUE) functions directly in LINQ queries with a fluent window specification API. +::: warning Not supported on EF Core 11 +EF Core 11 removed the SQL-generation fallback for third-party SQL expressions ([dotnet/efcore#37533](https://github.com/dotnet/efcore/pull/37533)), which the window function translation relies on. Until EF Core provides a replacement extension point (tracked in [dotnet/efcore#38977](https://github.com/dotnet/efcore/issues/38977)), the `RelationalExtensions` packages do not ship a `net11.0` target and EF Core 11 is unsupported. Applications on .NET 11 that need window functions should stay on EF Core 10, which runs fine on the .NET 11 runtime. All functions remain fully supported on EF Core 8, 9, and 10. +::: + ## Installation ```bash diff --git a/docs/index.md b/docs/index.md index 791d3c59..43b797dd 100644 --- a/docs/index.md +++ b/docs/index.md @@ -47,7 +47,7 @@ features: - icon: "\U0001F4CA" title: SQL Window Functions - details: "Ranking (ROW_NUMBER, RANK, DENSE_RANK, NTILE, PERCENT_RANK, CUME_DIST), aggregate (SUM, AVG, COUNT, MIN, MAX), and navigation (LAG, LEAD, FIRST_VALUE, LAST_VALUE, NTH_VALUE) functions with a fluent PARTITION BY / ORDER BY / frame API — via the RelationalExtensions package." + details: "Ranking (ROW_NUMBER, RANK, DENSE_RANK, NTILE, PERCENT_RANK, CUME_DIST), aggregate (SUM, AVG, COUNT, MIN, MAX), and navigation (LAG, LEAD, FIRST_VALUE, LAST_VALUE, NTH_VALUE) functions with a fluent PARTITION BY / ORDER BY / frame API — via the RelationalExtensions package (EF Core 8–10)." - icon: "\U0001F527" title: Customizable Transformer Pipeline @@ -116,4 +116,4 @@ Computed properties are **inlined into the provider's native query language** | [`ExpressiveSharp.Abstractions`](https://www.nuget.org/packages/ExpressiveSharp.Abstractions/) | Lightweight — attributes (`[Expressive]`, `[ExpressiveFor]`), `IExpressionTreeTransformer`, source generator only | | [`ExpressiveSharp.EntityFrameworkCore`](https://www.nuget.org/packages/ExpressiveSharp.EntityFrameworkCore/) | EF Core integration — `UseExpressives()`, `ExpressiveDbSet`, Include/ThenInclude, async methods | | [`ExpressiveSharp.MongoDB`](https://www.nuget.org/packages/ExpressiveSharp.MongoDB/) | MongoDB integration — `.AsExpressive()` on `IMongoCollection`, MQL translation | -| [`ExpressiveSharp.EntityFrameworkCore.RelationalExtensions`](https://www.nuget.org/packages/ExpressiveSharp.EntityFrameworkCore.RelationalExtensions/) | SQL window functions — ranking, aggregate, navigation with ROWS/RANGE frames | +| [`ExpressiveSharp.EntityFrameworkCore.RelationalExtensions`](https://www.nuget.org/packages/ExpressiveSharp.EntityFrameworkCore.RelationalExtensions/) | SQL window functions — ranking, aggregate, navigation with ROWS/RANGE frames (EF Core 8–10) | diff --git a/docs/recipes/window-functions-ranking.md b/docs/recipes/window-functions-ranking.md index 1136f982..30b29c77 100644 --- a/docs/recipes/window-functions-ranking.md +++ b/docs/recipes/window-functions-ranking.md @@ -2,6 +2,10 @@ This recipe shows how to use SQL window functions in EF Core LINQ queries via the `ExpressiveSharp.EntityFrameworkCore.RelationalExtensions` package. Coverage includes ranking (ROW_NUMBER, RANK, DENSE_RANK, NTILE, PERCENT_RANK, CUME_DIST), aggregate (SUM, AVG, COUNT, MIN, MAX), and navigation (LAG, LEAD, FIRST_VALUE, LAST_VALUE, NTH_VALUE) functions. +::: warning Not supported on EF Core 11 +The `RelationalExtensions` packages do not ship a `net11.0` target — EF Core 11 removed the SQL-generation fallback the window function translation relies on. See the [window functions guide](../guide/window-functions) for details and [dotnet/efcore#38977](https://github.com/dotnet/efcore/issues/38977) for tracking. On .NET 11, stay on EF Core 10. +::: + ## Setup Install the package: diff --git a/samples/EFCoreSample/EFCoreSample.csproj b/samples/EFCoreSample/EFCoreSample.csproj index 7181d13d..e9061488 100644 --- a/samples/EFCoreSample/EFCoreSample.csproj +++ b/samples/EFCoreSample/EFCoreSample.csproj @@ -14,6 +14,9 @@ + diff --git a/src/ExpressiveSharp.EntityFrameworkCore.RelationalExtensions.Abstractions/ExpressiveSharp.EntityFrameworkCore.RelationalExtensions.Abstractions.csproj b/src/ExpressiveSharp.EntityFrameworkCore.RelationalExtensions.Abstractions/ExpressiveSharp.EntityFrameworkCore.RelationalExtensions.Abstractions.csproj index be7a19a8..c9b562cd 100644 --- a/src/ExpressiveSharp.EntityFrameworkCore.RelationalExtensions.Abstractions/ExpressiveSharp.EntityFrameworkCore.RelationalExtensions.Abstractions.csproj +++ b/src/ExpressiveSharp.EntityFrameworkCore.RelationalExtensions.Abstractions/ExpressiveSharp.EntityFrameworkCore.RelationalExtensions.Abstractions.csproj @@ -2,6 +2,8 @@ Pure marker types for SQL window functions (ROW_NUMBER, RANK, DENSE_RANK, NTILE) with no EF Core dependency. Pair with ExpressiveSharp.EntityFrameworkCore.RelationalExtensions for EF Core SQL translation. + + net8.0;net9.0;net10.0 diff --git a/src/ExpressiveSharp.EntityFrameworkCore.RelationalExtensions/ExpressiveSharp.EntityFrameworkCore.RelationalExtensions.csproj b/src/ExpressiveSharp.EntityFrameworkCore.RelationalExtensions/ExpressiveSharp.EntityFrameworkCore.RelationalExtensions.csproj index d07e4595..d1b5effd 100644 --- a/src/ExpressiveSharp.EntityFrameworkCore.RelationalExtensions/ExpressiveSharp.EntityFrameworkCore.RelationalExtensions.csproj +++ b/src/ExpressiveSharp.EntityFrameworkCore.RelationalExtensions/ExpressiveSharp.EntityFrameworkCore.RelationalExtensions.csproj @@ -2,6 +2,11 @@ Relational database extensions for ExpressiveSharp EF Core — SQL window functions (ranking, aggregate, navigation) with PARTITION BY / ORDER BY / ROWS|RANGE frame support, plus indexed Select. + + net8.0;net9.0;net10.0 + $(NoWarn);NU5104 $(NoWarn);NU1903;NU1902;NU1901;NU1904 + + + true + true + + + true + + + + + $(DefineConstants);TEST_SQLSERVER - + $(DefineConstants);TEST_POSTGRES $(DefineConstants);TEST_COSMOS - + $(DefineConstants);TEST_POMELO_MYSQL @@ -36,6 +50,9 @@ + @@ -49,10 +66,13 @@ + - + @@ -77,10 +97,13 @@ + - - + + @@ -93,8 +116,10 @@ - - + + diff --git a/tests/ExpressiveSharp.EntityFrameworkCore.IntegrationTests/Infrastructure/CommonScenarioTestBase.cs b/tests/ExpressiveSharp.EntityFrameworkCore.IntegrationTests/Infrastructure/CommonScenarioTestBase.cs index 4c9a3f65..3c0bb46e 100644 --- a/tests/ExpressiveSharp.EntityFrameworkCore.IntegrationTests/Infrastructure/CommonScenarioTestBase.cs +++ b/tests/ExpressiveSharp.EntityFrameworkCore.IntegrationTests/Infrastructure/CommonScenarioTestBase.cs @@ -137,7 +137,7 @@ public virtual async Task Select_PriceBreakpoints_ReturnsArrayLiteral() } [TestMethod] - public async Task Select_OrderDto_ProjectsCorrectly() + public virtual async Task Select_OrderDto_ProjectsCorrectly() { Expression> expr = o => new OrderDto(o.Id, o.Tag ?? "N/A", o.Total); var expanded = (Expression>)expr.ExpandExpressives(); @@ -519,7 +519,7 @@ public async Task Polyfill_NullCoalescing_ProjectsCorrectly() } [TestMethod] - public async Task Select_Summary_ReturnsCorrectValues() + public virtual async Task Select_Summary_ReturnsCorrectValues() { Expression> expr = o => o.Summary; var expanded = (Expression>)expr.ExpandExpressives(); @@ -538,7 +538,7 @@ public async Task Select_Summary_ReturnsCorrectValues() } [TestMethod] - public async Task Select_SummaryConcat_ReturnsCorrectValues() + public virtual async Task Select_SummaryConcat_ReturnsCorrectValues() { Expression> expr = o => o.SummaryConcat; var expanded = (Expression>)expr.ExpandExpressives(); @@ -699,7 +699,7 @@ public virtual async Task Where_IsPriceQuantityMatch_FiltersCorrectly() } [TestMethod] - public async Task Select_InlineTuple_ProjectsCorrectly() + public virtual async Task Select_InlineTuple_ProjectsCorrectly() { var expr = ExpressionPolyfill.Create((Order o) => (o.Id, o.Price)); @@ -711,7 +711,7 @@ public async Task Select_InlineTuple_ProjectsCorrectly() } [TestMethod] - public async Task Select_TupleWithExpressiveMember_ProjectsCorrectly() + public virtual async Task Select_TupleWithExpressiveMember_ProjectsCorrectly() { var expr = ExpressionPolyfill.Create((Order o) => (o.Id, o.Price * o.Quantity)); @@ -724,7 +724,7 @@ public async Task Select_TupleWithExpressiveMember_ProjectsCorrectly() } [TestMethod] - public async Task Select_TupleWithNullable_ProjectsCorrectly() + public virtual async Task Select_TupleWithNullable_ProjectsCorrectly() { var expr = ExpressionPolyfill.Create((Order o) => (o.Id, o.Tag ?? "none")); diff --git a/tests/ExpressiveSharp.EntityFrameworkCore.IntegrationTests/Infrastructure/TestContextFactories.cs b/tests/ExpressiveSharp.EntityFrameworkCore.IntegrationTests/Infrastructure/TestContextFactories.cs index 8fa4d84f..539da4ac 100644 --- a/tests/ExpressiveSharp.EntityFrameworkCore.IntegrationTests/Infrastructure/TestContextFactories.cs +++ b/tests/ExpressiveSharp.EntityFrameworkCore.IntegrationTests/Infrastructure/TestContextFactories.cs @@ -33,7 +33,12 @@ public static SqliteContextHandle CreateSqlite( var options = new DbContextOptionsBuilder() .UseSqlite(connection) + // RelationalExtensions does not target net11.0 (dotnet/efcore#38977). +#if NET11_0_OR_GREATER + .UseExpressives() +#else .UseExpressives(o => o.UseRelationalExtensions()) +#endif .Options; return new SqliteContextHandle(factory(options), connection); @@ -72,7 +77,11 @@ public static SqlServerContextHandle CreateSqlServer( var options = new DbContextOptionsBuilder() .UseSqlServer(connStr) +#if NET11_0_OR_GREATER + .UseExpressives() +#else .UseExpressives(o => o.UseRelationalExtensions()) +#endif .Options; return new SqlServerContextHandle(factory(options)); diff --git a/tests/ExpressiveSharp.EntityFrameworkCore.IntegrationTests/Tests/Cosmos/CommonScenarioTests.cs b/tests/ExpressiveSharp.EntityFrameworkCore.IntegrationTests/Tests/Cosmos/CommonScenarioTests.cs index d0e236de..8eec953d 100644 --- a/tests/ExpressiveSharp.EntityFrameworkCore.IntegrationTests/Tests/Cosmos/CommonScenarioTests.cs +++ b/tests/ExpressiveSharp.EntityFrameworkCore.IntegrationTests/Tests/Cosmos/CommonScenarioTests.cs @@ -242,5 +242,49 @@ public override Task Select_CustomerCountry_TwoLevelChain() Assert.Inconclusive("Cosmos DB drops null rows in null-conditional projections"); return Task.CompletedTask; } + +#if NET11_0_OR_GREATER + // EF Core 11 rc.1 Cosmos regressions in the rewritten System.Text.Json shaper, + // reproduced with vanilla EF Core (no ExpressiveSharp involved): constructor and + // interpolated-string projections throw "A part of the projection was undefined" + // when they include a JSON-null value or mix the key property with a coalesced + // member, and string-concat projections of int properties fail shaper compilation + // with an invalid int -> string Convert. Revisit at EF 11 GA. + public override Task Select_OrderDto_ProjectsCorrectly() + { + Assert.Inconclusive("EF Core 11 rc.1 Cosmos shaper regression"); + return Task.CompletedTask; + } + + public override Task Select_Summary_ReturnsCorrectValues() + { + Assert.Inconclusive("EF Core 11 rc.1 Cosmos shaper regression"); + return Task.CompletedTask; + } + + public override Task Select_SummaryConcat_ReturnsCorrectValues() + { + Assert.Inconclusive("EF Core 11 rc.1 Cosmos shaper regression"); + return Task.CompletedTask; + } + + public override Task Select_InlineTuple_ProjectsCorrectly() + { + Assert.Inconclusive("EF Core 11 rc.1 Cosmos shaper regression"); + return Task.CompletedTask; + } + + public override Task Select_TupleWithExpressiveMember_ProjectsCorrectly() + { + Assert.Inconclusive("EF Core 11 rc.1 Cosmos shaper regression"); + return Task.CompletedTask; + } + + public override Task Select_TupleWithNullable_ProjectsCorrectly() + { + Assert.Inconclusive("EF Core 11 rc.1 Cosmos shaper regression"); + return Task.CompletedTask; + } +#endif } #endif diff --git a/tests/ExpressiveSharp.Generator.Tests/ExpressiveSharp.Generator.Tests.csproj b/tests/ExpressiveSharp.Generator.Tests/ExpressiveSharp.Generator.Tests.csproj index b02c46cc..ee704574 100644 --- a/tests/ExpressiveSharp.Generator.Tests/ExpressiveSharp.Generator.Tests.csproj +++ b/tests/ExpressiveSharp.Generator.Tests/ExpressiveSharp.Generator.Tests.csproj @@ -12,6 +12,7 @@ + diff --git a/tests/ExpressiveSharp.Generator.Tests/Infrastructure/GeneratorTestBase.cs b/tests/ExpressiveSharp.Generator.Tests/Infrastructure/GeneratorTestBase.cs index af8f79ad..04792c4f 100644 --- a/tests/ExpressiveSharp.Generator.Tests/Infrastructure/GeneratorTestBase.cs +++ b/tests/ExpressiveSharp.Generator.Tests/Infrastructure/GeneratorTestBase.cs @@ -44,7 +44,9 @@ protected sealed class TestGeneratorRunResult protected IReadOnlyList GetDefaultReferences() { var references = Basic.Reference.Assemblies. -#if NET10_0_OR_GREATER +#if NET11_0_OR_GREATER + Net110 +#elif NET10_0_OR_GREATER Net100 #elif NET9_0 Net90 diff --git a/tests/ExpressiveSharp.IntegrationTests/ExpressiveSharp.IntegrationTests.csproj b/tests/ExpressiveSharp.IntegrationTests/ExpressiveSharp.IntegrationTests.csproj index 78b68eba..25634486 100644 --- a/tests/ExpressiveSharp.IntegrationTests/ExpressiveSharp.IntegrationTests.csproj +++ b/tests/ExpressiveSharp.IntegrationTests/ExpressiveSharp.IntegrationTests.csproj @@ -11,8 +11,8 @@ OutputItemType="Analyzer" ReferenceOutputAssembly="false" /> - - + + diff --git a/tests/ExpressiveSharp.Tests/ExpressiveSharp.Tests.csproj b/tests/ExpressiveSharp.Tests/ExpressiveSharp.Tests.csproj index 404e04c2..87044cfa 100644 --- a/tests/ExpressiveSharp.Tests/ExpressiveSharp.Tests.csproj +++ b/tests/ExpressiveSharp.Tests/ExpressiveSharp.Tests.csproj @@ -3,12 +3,22 @@ false true + + + true + + + + - - + +