Skip to content

Commit 3455924

Browse files
rojiCopilot
authored andcommitted
Add EF9 breaking change for EF.Constant/EF.Parameter in compiled queries (#5341)
Document that EF.Constant() and EF.Parameter() no longer work inside compiled queries (EF.CompileQuery/EF.CompileAsyncQuery) starting with EF Core 9, due to the reimplementation of EF.Constant to avoid query cache misses (dotnet/efcore#33674). Reported by user in dotnet/efcore#38150. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent d9fed7a commit 3455924

1 file changed

Lines changed: 33 additions & 0 deletions

File tree

entity-framework/core/what-is-new/ef-core-9.0/breaking-changes.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ EF Core 9 targets .NET 8. This means that existing applications that target .NET
3434
| [`ToString()` method now returns empty string for `null` instances](#nullable-tostring) | Low |
3535
| [Shared framework dependencies were updated to 9.0.x](#shared-framework-dependencies) | Low |
3636
| [EF tools no longer support .NET Framework projects](#ef-tools-no-netfx) | Low |
37+
| [`EF.Constant()` and `EF.Parameter()` no longer work inside compiled queries](#ef-constant-compiled) | Low |
3738

3839
## High-impact changes
3940

@@ -356,6 +357,38 @@ The current version of EF Core tools works with all supported EF Core versions a
356357

357358
Update your project to target .NET (e.g., .NET 8 or later). If your project currently targets .NET Framework, see the [porting guide](/dotnet/core/porting/) for information on migrating to .NET.
358359

360+
<a name="ef-constant-compiled"></a>
361+
362+
### `EF.Constant()` and `EF.Parameter()` no longer work inside compiled queries
363+
364+
[Tracking Issue #33674](https://github.com/dotnet/efcore/issues/33674)
365+
366+
#### Old behavior
367+
368+
In EF Core 8, <xref:Microsoft.EntityFrameworkCore.EF.Constant*> and <xref:Microsoft.EntityFrameworkCore.EF.Parameter*> could be used inside compiled queries (<xref:Microsoft.EntityFrameworkCore.EF.CompileQuery*> and <xref:Microsoft.EntityFrameworkCore.EF.CompileAsyncQuery*>):
369+
370+
```csharp
371+
var lookbackDays = 7;
372+
373+
var compiledQuery = EF.CompileAsyncQuery(
374+
(AppDbContext db) => db.Blogs
375+
.Where(b => b.PublishedOn >= DateTime.Today.AddDays(EF.Constant(-lookbackDays))));
376+
```
377+
378+
#### New behavior
379+
380+
Starting with EF Core 9.0, using <xref:Microsoft.EntityFrameworkCore.EF.Constant*> or <xref:Microsoft.EntityFrameworkCore.EF.Parameter*> inside a compiled query throws an `InvalidCastException`:
381+
382+
> :::no-loc text="Unable to cast object of type 'System.Linq.Expressions.ConstantExpression' to type 'System.Linq.Expressions.ParameterExpression'.":::
383+
384+
#### Why
385+
386+
The internal implementation of <xref:Microsoft.EntityFrameworkCore.EF.Constant*> was changed to avoid full query recompilation for each different constant value. The previous implementation introduced constant nodes early in the query pipeline (before query caching), causing expensive cache misses whenever a different value was passed to `EF.Constant()`. The new implementation processes these methods at a later stage, which is incompatible with compiled queries.
387+
388+
#### Mitigations
389+
390+
Either remove the <xref:Microsoft.EntityFrameworkCore.EF.Constant*> or <xref:Microsoft.EntityFrameworkCore.EF.Parameter*> call from the compiled query, or stop using a compiled query for that particular query. Note that removing `EF.Constant()` causes the value to be sent as a SQL parameter rather than inlined as a constant, which may affect query plan performance.
391+
359392
## Azure Cosmos DB breaking changes
360393

361394
Extensive work has gone into making the Azure Cosmos DB provider better in 9.0. The changes include a number of high-impact breaking changes; if you are upgrading an existing application, please read the following carefully.

0 commit comments

Comments
 (0)