Skip to content

Throw for a shadow Many-To-Many navigation #23362

Closed

Description

When calling Include() on Polymorphic Many-To-Many collections, an exception is thrown:

System.ArgumentException
  HResult=0x80070057
  Message=Method 'Boolean Add(System.Object, System.Object, Boolean)' declared on type 'Microsoft.EntityFrameworkCore.Metadata.IClrCollectionAccessor' cannot be called with instance of type 'System.Object'
  Source=System.Linq.Expressions
  StackTrace:
   at System.Linq.Expressions.Expression.ValidateCallInstanceType(Type instanceType, MethodInfo method)
   at System.Linq.Expressions.Expression.ValidateStaticOrInstanceMethod(Expression instance, MethodInfo method)
   at System.Linq.Expressions.Expression.ValidateMethodAndGetParameters(Expression instance, MethodInfo method)
   at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, Expression arg0, Expression arg1, Expression arg2)
   at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryShapedQueryCompilingExpressionVisitor.CustomShaperCompilingExpressionVisitor.AddToCollectionNavigation(ParameterExpression entity, ParameterExpression relatedEntity, INavigationBase navigation)
   at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryShapedQueryCompilingExpressionVisitor.CustomShaperCompilingExpressionVisitor.GenerateFixup(Type entityType, Type relatedEntityType, INavigationBase navigation, INavigationBase inverseNavigation)
   at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryShapedQueryCompilingExpressionVisitor.CustomShaperCompilingExpressionVisitor.VisitExtension(Expression extensionExpression)
   at System.Linq.Expressions.Expression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at System.Dynamic.Utils.ExpressionVisitorUtils.VisitBlockExpressions(ExpressionVisitor visitor, BlockExpression block)
   at System.Linq.Expressions.ExpressionVisitor.VisitBlock(BlockExpression node)
   at System.Linq.Expressions.BlockExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at System.Linq.Expressions.ExpressionVisitor.VisitLambda[T](Expression`1 node)
   at System.Linq.Expressions.Expression`1.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryShapedQueryCompilingExpressionVisitor.VisitShapedQuery(ShapedQueryExpression shapedQueryExpression)
   at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.VisitExtension(Expression extensionExpression)
   at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryShapedQueryCompilingExpressionVisitor.VisitExtension(Expression extensionExpression)
   at System.Linq.Expressions.Expression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   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__DisplayClass9_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
   at System.Linq.Queryable.Single[TSource](IQueryable`1 source)
   at EfCore5Tests.Program.Main(String[] args) in D:\Projects\Sandbox\EfCore5Tests\Program.cs:line 55

The used DbContext is:

    public class DemoContext : DbContext {

        public DbSet<User> Users { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
            base.OnConfiguring(optionsBuilder);
            optionsBuilder.UseInMemoryDatabase("Test");
        }

        protected override void OnModelCreating(ModelBuilder mb) {
            base.OnModelCreating(mb);
            mb.Entity<Project>(e => e.HasKey(x => x.Id));
            mb.Entity<InternalProject>();
            mb.Entity<CustomerProject>();
            mb.Entity<User>(e => e.HasMany(x => x.Projects).WithMany("Users"));
        }
    }

The query is:

    class Program {
        static void Main(string[] args) {
            var db = new DemoContext();
            var p1 = new InternalProject();
            var p2 = new CustomerProject();
            var user = new User { Projects = { p1, p2 } };

            db.AddRange(p1, p2, user);
            db.SaveChanges();

            db = new DemoContext();
            
            User actual = db.Set<User>().Include(x => x.Projects).Single();

            foreach (var p in actual.Projects) {
                Console.WriteLine(p);
            }
        }
    }

The model classes are:

    public class User {
        public Guid Id { get; set; } = Guid.NewGuid();

        public List<Project> Projects { get; set; } = new List<Project>();
    }

    public class Project {
        public Guid Id { get; set; } = Guid.NewGuid();
    }

    public class InternalProject : Project {
        public string Name { get; set; }
    }

    public class CustomerProject : Project {
        public decimal Costs { get; set; }
    }

EF Core version: 5
Database provider: Microsoft.EntityFrameworkCore.InMemory
Target framework: .NET 5.0
Operating system: Win 10

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions