EntityCommandCompilationException when using .Include() on class with subclass
jehhynes opened this issue · 2 comments
Description
When using DbSet.Include(x => x.Relationship) where Relationship is a type which has a subclass, we receive a EntityCommandCompilationException.
I've included the full exception below, and a test case which will run in the DynamicFiltersTests project (and fail with the following exception). This is using the latest codebase on master.
Exception
Message:
Test method DynamicFiltersTests.NavigationTests.FilterIncludesWithSubclass threw exception:
System.Data.Entity.Core.EntityCommandCompilationException: An error occurred while preparing the command definition. See the inner exception for details. ---> System.ArgumentException: The specified navigation requires a navigation source of a type that is compatible with 'Transient.reference[DynamicFiltersTests.Employee]'.
Parameter name: from
Stack Trace:
at ArgumentValidation.RequireCompatibleType(DbExpression from, RelationshipEndMember end, Boolean allowAllRelationshipsInSameTypeHierarchy)
at ArgumentValidation.ValidateNavigate(DbExpression navigateFrom, RelationshipEndMember fromEnd, RelationshipEndMember toEnd, RelationshipType& relType, Boolean allowAllRelationshipsInSameTypeHierarchy)
at DbExpressionBuilder.Navigate(DbExpression navigateFrom, RelationshipEndMember fromEnd, RelationshipEndMember toEnd)
at DefaultExpressionVisitor.Visit(DbRelationshipNavigationExpression expression)
at DbRelationshipNavigationExpression.Accept[TResultType](DbExpressionVisitor`1 visitor)
at DefaultExpressionVisitor.VisitExpression(DbExpression expression)
at DefaultExpressionVisitor.VisitList[TElement](IList`1 list, Func`2 map)
at DefaultExpressionVisitor.VisitExpressionList(IList`1 list)
at DefaultExpressionVisitor.Visit(DbNewInstanceExpression expression)
at DynamicFilterQueryVisitorCSpace.Visit(DbNewInstanceExpression expression) in DynamicFilterQueryVisitorCSpace.cs line: 396
at DbNewInstanceExpression.Accept[TResultType](DbExpressionVisitor`1 visitor)
at DefaultExpressionVisitor.VisitExpression(DbExpression expression)
at DefaultExpressionVisitor.VisitList[TElement](IList`1 list, Func`2 map)
at DefaultExpressionVisitor.VisitExpressionList(IList`1 list)
at DefaultExpressionVisitor.Visit(DbNewInstanceExpression expression)
at DynamicFilterQueryVisitorCSpace.Visit(DbNewInstanceExpression expression) in DynamicFilterQueryVisitorCSpace.cs line: 396
at DbNewInstanceExpression.Accept[TResultType](DbExpressionVisitor`1 visitor)
at DefaultExpressionVisitor.VisitExpression(DbExpression expression)
at DefaultExpressionVisitor.Visit(DbProjectExpression expression)
at DynamicFilterQueryVisitorCSpace.Visit(DbProjectExpression expression) in DynamicFilterQueryVisitorCSpace.cs line: 418
at DbProjectExpression.Accept[TResultType](DbExpressionVisitor`1 visitor)
at DynamicFilterInterceptor.TreeCreated(DbCommandTreeInterceptionContext interceptionContext) in DynamicFilterInterceptor.cs line: 43
at DbCommandTreeDispatcher.<Created>b__0(IDbCommandTreeInterceptor i, DbCommandTreeInterceptionContext c)
at InternalDispatcher`1.Dispatch[TInterceptionContext,TResult](TResult result, TInterceptionContext interceptionContext, Action`2 intercept)
at DbCommandTreeDispatcher.Created(DbCommandTree commandTree, DbInterceptionContext interceptionContext)
at DbProviderServices.CreateCommandDefinition(DbCommandTree commandTree, DbInterceptionContext interceptionContext)
at ObjectQueryExecutionPlanFactory.CreateCommandDefinition(ObjectContext context, DbQueryCommandTree tree)
at --- End of inner exception stack trace ---
at ObjectQueryExecutionPlanFactory.CreateCommandDefinition(ObjectContext context, DbQueryCommandTree tree)
at ObjectQueryExecutionPlanFactory.Prepare(ObjectContext context, DbQueryCommandTree tree, Type elementType, MergeOption mergeOption, Boolean streaming, Span span, IEnumerable`1 compiledQueryParameters, AliasGenerator aliasGenerator)
at EntitySqlQueryState.GetExecutionPlan(Nullable`1 forMergeOption)
at <>c__DisplayClass7.<GetResults>b__6()
at ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess)
at <>c__DisplayClass7.<GetResults>b__5()
at DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation)
at ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
at IEnumerable<T>.GetEnumerator>b__0()
at LazyEnumerator`1.MoveNext()
at List`1.ctor(IEnumerable`1 collection)
at Enumerable.ToList[TSource](IEnumerable`1 source)
at NavigationTests.FilterIncludesWithSubclass() in NavigationTests.cs line: 21
Exception message:
Stack trace:
Fiddle or Project
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
using EntityFramework.DynamicFilters;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace DynamicFiltersTests
{
[TestClass]
public class NavigationTests
{
[TestMethod]
public void FilterIncludesWithSubclass()
{
using (var context = new TestContext())
{
var list = context.Entity1s
.Include(x => x.User)
.ToList();
}
}
#region Models
public class Depot : PersistentObject, IFilterTenant
{
public virtual Tenant Tenant { get; set; }
}
public class Employee : UserAccount
{
public virtual Depot Depot { get; set; }
}
public class UserAccount : PersistentObject, IFilterTenant
{
public virtual Tenant Tenant { get; set; }
}
public class Entity1 : PersistentObject, IFilterTenant
{
[ForeignKey("Id")]
public virtual UserAccount User { get; set; }
public virtual Tenant Tenant { get; set; }
}
public class Tenant : PersistentObject
{
}
public interface IPersistentObject
{
long Id { get; set; }
}
public abstract class PersistentObject : IPersistentObject
{
[Key]
public virtual long Id { get; set; }
}
#endregion
#region TestContext
public class TestContext : TestContextBase<TestContext>, ITestContext
{
public long? FilterTenantId { get; set; }
public DbSet<Tenant> Tenants { get; set; }
public DbSet<UserAccount> UserAccounts { get; set; }
public DbSet<Depot> Depots { get; set; }
public DbSet<Entity1> Entity1s { get; set; }
public override void Seed()
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Filter<IFilterTenant, TestContext, long?>("TenantFilter", (o, id) => o.Tenant.Id == id, ctx => ctx.FilterTenantId);
}
}
public interface IHasTenant
{
Tenant Tenant { get; set; }
}
public interface IFilterTenant : IHasTenant { }
#endregion
}
}
Further technical details
- EF version: 6.1.3 (what's currently referenced on master)
- EF DynamicFilters version: Current 'master' branch
- Database Provider: mssqllocaldb (probably any provider)
Hello @jehhynes ,
Thank you for reporting, we will look at it if that's possible to support this.
Best Regards,
Jonathan
Performance Libraries
context.BulkInsert(list, options => options.BatchSize = 1000);
Entity Framework Extensions • Entity Framework Classic • Bulk Operations • Dapper Plus
Runtime Evaluation
Eval.Execute("x + y", new {x = 1, y = 2}); // return 3
C# Eval Function • SQL Eval Function
Hello @jehhynes ,
My developer and me tried to find a fix but unfortunately, both of us failed without any progression.
So we choose to leave the issue open but stop to work on it until we get another idea to try or another issue that gives us some hint that might lead to a resolution.