ExecuteUpdateAsync breaks with Many-To-Many and AutoInclude
- Dominant language
- C#
- Stars
- 14.8k
- Forks
- 3.4k
- PR merge metrics
- PR metrics pending
Description
### Bug description
Configuring an entity to `AutoInclude` a many-to-many relationship renders `ExecuteUpdateAsync` dysfunctional.
I found https://github.com/dotnet/efcore/issues/30250 which is closed as duplicate to a resolved issue almost 2 years ago however it's reproducible in the most recent stable version. It seems the bug is only reproducible with many-to-many relationships at this point (the linked issue did not seem to cover that scenario).
### Your code
```xml
net9.0
enable
enable
```
```csharp
// Program.cs
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddDbContext(options => options.UseSqlite("Data Source=:memory:"));
var app = builder.Build();
await using var scope = app.Services.CreateAsyncScope();
var brokenContext = scope.ServiceProvider.GetRequiredService();
await brokenContext.Database.MigrateAsync();
await brokenContext.BrokenModels.ExecuteUpdateAsync(calls => calls.SetProperty(m => m.Property, ""));
public class BrokenModel {
public Guid Id { get; set; }
public string Property { get; set; } = "";
public IEnumerable Relationships { get; set; }
}
public class BrokenRelationship {
public Guid Id { get; set; }
public IEnumerable BrokenModels { get; set; }
}
public class BrokenContext : DbContext{
public DbSet BrokenModels { get; set; } = null!;
public DbSet BrokenRelationships { get; set; } = null!;
public BrokenContext(DbContextOptions options): base(options) {
}
protected override void OnModelCreating(ModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
modelBuilder.Entity().Navigation(m => m.Relationships).AutoInclude();
}
}
```
### Stack traces
```text
Unhandled exception. System.InvalidOperationException: The LINQ expression 'DbSet()
.Select(b0 => Include(
Entity: b0,
Navigation: Relationships, MaterializeCollectionNavigation(
Navigation: BrokenModel.Relationships,
Subquery: DbSet>("BrokenModelBrokenRelationship")
.Where(b1 => EF.Property(b0, "Id") != null && object.Equals(
objA: (object)EF.Property(b0, "Id"),
objB: (object)EF.Property(b1, "BrokenModelsId")))
.Join(
inner: DbSet(),
outerKeySelector: b1 => (object)EF.Property(b1, "RelationshipsId"),
innerKeySelector: b2 => (object)EF.Property(b2, "Id"),
resultSelector: (b1, b2) => new TransparentIdentifier, BrokenRelationship>(
Outer = b1,
Inner = b2
))
.Select(ti => NavigationExpandingExpressionVisitor.FetchJoinEntity, BrokenRelationship>(
joinEntity: ti.Outer,
targetEntity: ti.Inner))))
.ExecuteUpdate(calls => calls.SetProperty(
propertyExpression: m => m.Property,
valueExpression: ""))' could not be translated. Additional information: The following lambda argument to 'SetProperty' does not represent a valid property to be set: 'm => m.Property'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.Translate(Expression expression)
at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutorExpression[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass11_0`1.b__0()
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteCore[TResult](Expression query, Boolean async, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ExecuteUpdateAsync[TSource](IQueryable`1 source, Expression`1 setPropertyCalls, CancellationToken cancellationToken)
at Program.$(String[] args) in D:\playground\Program.cs:line 13
at Program.$(String[] args) in D:\playground\Program.cs:line 13
at Program.(String[] args)
```
### EF Core version
9.0.1
### Database provider
Microsoft.EntityFrameworkCore.Sqlite
### Target framework
.NET 9.0
### Operating system
Windows 11
### IDE
Rider 2024.3.3
Contributor guide
Assessment
This issue has not been assessed yet.