Efcore: Owned collection when owner has composite PK throws translation failure

Created on 29 Oct 2020  路  6Comments  路  Source: dotnet/efcore

I created a model where I have OwnsMany property used on 2 levels. Code sample below

```using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;

namespace EFProjectionRepro
{
public class Context : DbContext
{
public DbSet Entities => Set();

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        base.OnConfiguring(optionsBuilder);
        optionsBuilder.UseSqlServer("Server=localhost,1433;User Id=sa;Password=Password1!");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Entity>(cfg =>
        {
            cfg.OwnsMany(e => e.Children, inner =>
            {
                inner.OwnsMany(e => e.Owned);
            });
        });
    }
}

public class Entity
{
    public int Id { get; set; }
    public List<Child> Children { get; set; }
}

public class Child
{
    public int Id { get; set; }
    public int Type { get; set; }
    public List<Owned> Owned { get; set; }
}

public class Owned
{
    public string Value { get; set; }
}

}

```using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace EFProjectionRepro
{
    class Program
    {
        static async Task Main(string[] args)
        {
            using var dbContext = new Context();

            dbContext.Entities.Add(new Entity());
            await dbContext.SaveChangesAsync();
            await dbContext.Entities.ToListAsync();
        }
    }
}

When running saving Entity works, but when trying to read Entity from sql database (await dbContext.Entities.ToListAsync();) I get exception:

```Unhandled exception. System.InvalidOperationException: The LINQ expression 'ShapedQueryExpression:
QueryExpression:
Projection Mapping:
EmptyProjectionMember -> [EntityProjectionExpression]
SELECT 1
FROM Owned AS o
ShaperExpression: EntityShaperExpression:
EntityType: Owned
ValueBufferExpression:
ProjectionBindingExpression: EmptyProjectionMember
IsNullable: False

.Where(namelessParameter{0} => new object[]
{ 
    (object)EF.Property<int>(EntityShaperExpression: 
        EntityType: Child
        ValueBufferExpression: 
            ProjectionBindingExpression: EmptyProjectionMember
        IsNullable: False
    , "EntityId"), 
    (object)EF.Property<int>(EntityShaperExpression: 
        EntityType: Child
        ValueBufferExpression: 
            ProjectionBindingExpression: EmptyProjectionMember
        IsNullable: False
    , "Id") 
} != null && new object[]
{ 
    (object)EF.Property<int>(EntityShaperExpression: 
        EntityType: Child
        ValueBufferExpression: 
            ProjectionBindingExpression: EmptyProjectionMember
        IsNullable: False
    , "EntityId"), 
    (object)EF.Property<int>(EntityShaperExpression: 
        EntityType: Child
        ValueBufferExpression: 
            ProjectionBindingExpression: EmptyProjectionMember
        IsNullable: False
    , "Id") 
} == new object[]
{ 
    (object)EF.Property<int>(namelessParameter{0}, "ChildEntityId"), 
    (object)EF.Property<int>(namelessParameter{0}, "ChildId") 
})' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.g__CheckTranslated|15_0(ShapedQueryExpression translated, <>c__DisplayClass15_0& )
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.TranslateSubquery(Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.IncludeExpression.VisitChildren(ExpressionVisitor visitor)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitExtension(Expression extensionExpression)
at System.Linq.Expressions.Expression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Translate(SelectExpression selectExpression, Expression expression)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateSelect(ShapedQueryExpression source, LambdaExpression selector)
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.TranslateSubquery(Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.IncludeExpression.VisitChildren(ExpressionVisitor visitor)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitExtension(Expression extensionExpression)
at System.Linq.Expressions.Expression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Translate(SelectExpression selectExpression, Expression expression)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateSelect(ShapedQueryExpression source, LambdaExpression selector)
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutorTResult
at Microsoft.EntityFrameworkCore.Storage.Database.CompileQueryTResult
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCoreTResult
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass12_01.<ExecuteAsync>b__0() at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func1 compiler)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsyncTResult
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsyncTResult
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable1.GetAsyncEnumerator(CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Internal.InternalDbSet1.System.Collections.Generic.IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken)
at System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable1.GetAsyncEnumerator() at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable1 source, CancellationToken cancellationToken)
at EFProjectionRepro.Program.Main(String[] args) in route/to/file.cs:line 17
at EFProjectionRepro.Program.

(String[] args)
```

Switching the model to HasMany for both Child and Owned does not cause exception.

EF Core version: 5.0.0-rc.2.20475.6
Database provider:Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 5.0
Operating system: Ubuntu 18.04
IDE: Visual Studio Code 1.50.1

Servicing-approved closed-fixed customer-reported regression type-bug

Most helpful comment

All 6 comments

@smitpatel Regression?

@ajcvickers - Possible. Many changes affected this area in 5.0. I did not test on 3.1

@ajcvickers - Confirmed this regression from 3.1 release.

@smitpatel Let's prepare a fix for Tactics.

Was this page helpful?
0 / 5 - 0 ratings