SelectMany fails when projecting an entity with an owned entity into an anonymous type
- Dominant language
- C#
- Stars
- 14.8k
- Forks
- 3.4k
- PR merge metrics
- PR metrics pending
Description
### Bug description
When using `SelectMany` on an entity that has an owned entity type in Entity Framework, the query fails with the `System.InvalidOperationException: Table not found with alias 'd'`. The issue occurs when selecting from an entity containing an owned entity type and projecting to an anonymous type inside the `SelectMany` call:
```c#
await context.Set()
.SelectMany(x => x.Versions.Select(y => new { d = x, v = y }))
.ToListAsync();
```
I found a workaround by using a different overload of the `SelectMany` method:
```c#
await context.Set()
.SelectMany(x => x.Versions, (d, v) => new {d, v})
.ToListAsync();
```
### Your code
```csharp
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
public class DocumentTest
{
public int Id { get; init; }
public List Versions { get; init; } = new List();
public MarginOptions PrintMargin { get; init; } = MarginOptions.Default;
}
public class VersionTest
{
public int Id { get; init; }
public int Number { get; init; }
}
public record MarginOptions(int Top, int Bottom, int Left, int Right)
{
public static MarginOptions Default => new MarginOptions(15, 15, 15, 15);
}
public class VersionTestConfiguration : IEntityTypeConfiguration
{
public void Configure(EntityTypeBuilder builder)
{
builder.HasKey(x => x.Id);
}
}
public class DocumentTestConfiguration : IEntityTypeConfiguration
{
public void Configure(EntityTypeBuilder builder)
{
builder.HasKey(x => x.Id);
builder.OwnsOne(x => x.PrintMargin);
builder.HasMany(x => x.Versions).WithOne();
}
}
public class ApplicationDbContext : DbContext
{
public DbSet Documents { get; set; }
public DbSet Versions { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseNpgsql("Host=localhost;Database=testdb;Username=postgres;Password=yourpassword");
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new DocumentTestConfiguration());
modelBuilder.ApplyConfiguration(new VersionTestConfiguration());
}
}
class Program
{
static async Task Main(string[] args)
{
await using var context = new ApplicationDbContext();
await context.Database.MigrateAsync();
var document = new DocumentTest
{
Id = 1,
Versions = new List
{
new VersionTest { Id = 1, Number = 1 },
new VersionTest { Id = 2, Number = 2 }
}
};
context.Documents.Add(document);
await context.SaveChangesAsync();
var result = await context.Set()
.SelectMany(x => x.Versions.Select(y => new { d = x, v = y }))
.ToListAsync();
foreach (var item in result)
{
Console.WriteLine($"Document ID: {item.d.Id}, Version ID: {item.v.Id}");
}
}
}
```
### Stack traces
```text
Unhandled exception. System.InvalidOperationException: Table not found with alias 'd'
at Microsoft.EntityFrameworkCore.Query.SqlExpressions.SelectExpression.GetTable(ColumnExpression column)
at Microsoft.EntityFrameworkCore.Query.SqlExpressions.SelectExpression.g__GetPropertyExpressions|84_0(ISqlExpressionFactory sqlExpressionFactory, SqlAliasManager sqlAliasManager, INavigation navigation, SelectExpression selectExpression, ColumnExpression identifyingColumn)
at Microsoft.EntityFrameworkCore.Query.SqlExpressions.SelectExpression.g__GetPropertyExpressions|84_0(ISqlExpressionFactory sqlExpressionFactory, SqlAliasManager sqlAliasManager, INavigation navigation, SelectExpression selectExpression, ColumnExpression identifyingColumn)
at Microsoft.EntityFrameworkCore.Query.SqlExpressions.SelectExpression.GenerateOwnedReferenceEntityProjectionExpression(StructuralTypeProjectionExpression principalEntityProjection, INavigation navigation, ISqlExpressionFactory sqlExpressionFactory, SqlAliasManager sqlAliasManager)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.SharedTypeEntityExpandingExpressionVisitor.<>c__DisplayClass8_0.g__ExpandOwnedNavigation|0(INavigation navigation)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.SharedTypeEntityExpandingExpressionVisitor.TryExpand(Expression source, MemberIdentity member)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.SharedTypeEntityExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at Microsoft.EntityFrameworkCore.Query.IncludeExpression.VisitChildren(ExpressionVisitor visitor)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.SharedTypeEntityExpandingExpressionVisitor.VisitExtension(Expression extensionExpression)
at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)
at System.Linq.Expressions.ExpressionVisitor.VisitNew(NewExpression node)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.SharedTypeEntityExpandingExpressionVisitor.Expand(SelectExpression selectExpression, Expression lambdaBody)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.ExpandSharedTypeEntities(SelectExpression selectExpression, Expression lambdaBody)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.RemapLambdaBody(ShapedQueryExpression shapedQueryExpression, LambdaExpression lambdaExpression)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateSelect(ShapedQueryExpression source, LambdaExpression selector)
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.Query.Internal.EntityQueryable`1.GetAsyncEnumerator(CancellationToken cancellationToken)
at System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1.GetAsyncEnumerator()
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
at Program.Main(String[] args) in /Users/timur/Documents/GitHub/slp/backend/ConsoleApp1/Program.cs:line 75
at Program.Main(String[] args) in /Users/timur/Documents/GitHub/slp/backend/ConsoleApp1/Program.cs:line 79
at Program.(String[] args)
Process finished with exit code 134.
```
### Verbose output
```text
```
### EF Core version
9.0.2, 9.0.3
### Database provider
PostgreSQL
### Target framework
.NET 9
### Operating system
macOS
### IDE
Rider
Contributor guide
Assessment
This issue has not been assessed yet.