efcore: EF Core 3: "Lambda expression used inside Include is not valid" with inherited entity property
In the context of a inherited entities, I want to get the full structure, given the fact a sub element has a type that is a super type.
In this example, I want to get the full list of historical values, with their dependencies: if the dependency is a shareclass, I want to get the related subfund on the go
Steps to reproduce
This code works 👍
var tmp = _dbContext.Set<Security>()
.Include(i => (i as ShareClass).SubFund)
.ToList();
This code fails 💥
FYI: It worked in EF and EF Core prior 3.0
var tmp = _dbContext.Set<SecurityHistoricalValue>()
.Include(i => i.Security as ShareClass).ThenInclude(i => i.SubFund)
.ToList();
Typically, here is the regex pattern that permits me to find what will raise an exception on my code after my migration to EF core 3.0:
as\s+[^\s]+[)]\s*[.]ThenInclude\s*[(]
Exception raised:
Exception thrown: 'System.InvalidOperationException' in Microsoft.EntityFrameworkCore.dll: 'Lambda expression used inside Include is not valid.'
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.ProcessInclude(NavigationExpansionExpression source, Expression expression, Boolean thenInclude)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.ExpandAndReduce(Expression query, Boolean applyInclude)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.Expand(Expression query)
at Microsoft.EntityFrameworkCore.Query.QueryTranslationPreprocessor.Process(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__DisplayClass9_0`1.<Execute>b__0()
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func`1 compiler)
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 Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetEnumerator()
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.IncludableQueryable`2.GetEnumerator()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at FundProcess.Pms.Services.PortfolioService.<SearchHistoricalValuesAsync>d__5.MoveNext() in /home/stephane/Documents/Sources/PMS/src/FundProcess.Pms.Services/PortfolioService.cs:line 93
SubFund entity definition 🔧
public class SubFund
{
}
public class SubFundConfiguration : IEntityTypeConfiguration<SubFund>
{
public void Configure(EntityTypeBuilder<SubFund> builder)
{
builder.HasBaseType<Portfolio>();
}
}
Security entity definition 🔧
public abstract class Security : IBelongsToEntity, IAnySecurity
{
public int Id { get; set; }
public List<SecurityHistoricalValue> HistoricalValues { get; set; }
}
public class SecurityConfiguration : IEntityTypeConfiguration<Security>
{
public void Configure(EntityTypeBuilder<Security> builder)
{
builder.ToTable(nameof(Security));
builder.HasKey(i => i.Id);
builder.Property(i => i.Id).UseIdentityColumn();
}
}
ShareClass entity definition 🔧
public class ShareClass : Security
{
public int? SubFundId { get; set; }
public SubFund SubFund { get; set; }
}
public class ShareClassConfiguration : IEntityTypeConfiguration<ShareClass>
{
public void Configure(EntityTypeBuilder<ShareClass> builder)
{
builder.HasBaseType<Security>();
builder.HasOne(i => i.SubFund).WithMany(i=>i.ShareClasses).OnDelete(DeleteBehavior.Restrict).HasForeignKey(i => i.SubFundId);
}
}
Future entity definition 🔧
public class Future : Security
{
}
public class ShareClassConfiguration : IEntityTypeConfiguration<Future>
{
public void Configure(EntityTypeBuilder<Future> builder)
{
}
}
SecurityHistoricalValue definition 🔧
public class SecurityHistoricalValue
{
public int SecurityId { get; set; }
public Security Security { get; set; }
public DateTime Date { get; set; }
}
public class SecurityHistoricalValueConfiguration : IEntityTypeConfiguration<SecurityHistoricalValue>
{
public void Configure(EntityTypeBuilder<SecurityHistoricalValue> builder)
{
builder.ToTable(nameof(SecurityHistoricalValue));
builder.Property(i => i.Date).HasColumnType("DATE");
builder.HasKey(i => new { i.Date, i.SecurityId});
builder.HasOne(i => i.Security).WithMany(i => i.HistoricalValues).OnDelete(DeleteBehavior.Restrict).HasForeignKey(i => i.SecurityId);
}
}
Further technical details
EF Core version: 3.0 Database provider: Microsoft.EntityFrameworkCore.SqlServer Target framework: .NET Core 3.0 Operating system: ubuntu 19.04 IDE: VIsual Studio Code
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 21
- Comments: 38 (13 by maintainers)
I have similar issue that works in ef core 2.2.6, but it is not working in 3.1.1
Same for EF Core 3.1.2
Edit: Solved my problem. The problem was a property that had only a getter and not a setter. I added a private setter and now .ThenInclude works fine.
The
Exception thrown: 'System.InvalidOperationException' in Microsoft.EntityFrameworkCore.dll: 'Lambda expression used inside Include is not valid.'
was really confusingThe solution for me was adding the relationship to the modelbuilder.
So for example, my query includes an City.
My Property that i use in my include looks like:
And i define the relationship in the modelbuilder, and that solved the problem with the invalid lambda expression.
It looks like that Entity Framework can’t resolve the relationship at his own, so with the Modelbuilder you define the relations at your own. I know this is a simple example, but this also should work with bigger relationships.
I hope this is the solution for you all!
PS: I don’t use lazy loading, i use eager loading.
query = query.Include(x => x.Items).ThenInclude(y => y.Select(z => z.Prodct));
this ex won’t work, how do this?
@PeterLAxakon - The feature was added in EF Core 5.0. If it is not working on EF Core 5.0 then please file a new issue with repro steps.
When using the name of the property with the same name of your entity, do you have this problem because in EntityFramework Core 3.0 is removed relation of the foreign key by convention. Look this the breaking changes on the new version after 2.2.
https://docs.microsoft.com/pt-br/ef/core/what-is-new/ef-core-3.0/breaking-changes#the-foreign-key-property-convention-no-longer-matches-same-name-as-the-principal-property
It did not worked out for me, my solution is to concat the results like this:
I know it’s not very elegant, but for me it works for the moment.
@smitpatel I can confirm that both versions provided by @ajcvickers do not work for me. This is currently preventing me from upgrading to 3.0.
There is no doubt that our use cases are more like corner cases. But it is somehow a regression since the aforementioned worked in v2.2. and also it is a feature that I would suspect to be working when inheritance is supported by the Framework.
Include(e => EF.Property<T>(e, propertyInfo.Name))
would be much simpler. (This assumes the navigation name is same as propertyInfo.Name)or string based include
Include(propertyInfo.Name)
@ptsneves - That is not valid include. You cannot use cast on navigation.
@rochapablo Include can only be used with navigation properties configured in the model.
[NotMapped]
explicitly excludes this property from the model, so Include cannot be used here. This is because without a mapping for the navigation property in the model, EF would not know which related entities to include.To add to above,
Select
inside include is not supported.Also anyone seeing the same exception, make sure that the navigation you are trying to include is actually mapped in your model.
@rochapablo and others commenting on this issue: can you provide some more details on why you cannot or it is hard to use the form of Include that is supported?
Same problem here. Is there any news about this issue?
@amacado @domdeger - Use 3.1 release. That is latest LTS release out there. If it does not work then share runnable repro code which demonstrate error you are hitting.
@smitpatel i already tried that. Have the same problem as @domdeger that it still not work.
For me no version does work. I just migrated from EF Core 2.2 to EF Core 3.0. Following code where Values is List ofSectionType causes a similar exception and I did not find a way to make that include work:
Exception:
An unhandled exception has occurred while executing the request. System.InvalidOperationException: Invalid include. at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.PopulateIncludeTree(IncludeTreeNode includeTreeNode, Expression expression) at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.ProcessInclude(NavigationExpansionExpression source, Expression expression, Boolean thenInclude) at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor) at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.ExpandAndReduce(Expression query, Boolean applyInclude) at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.Expand(Expression query) at Microsoft.EntityFrameworkCore.Query.QueryTranslationPreprocessor.Process(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__DisplayClass12_0
1.<ExecuteAsync>b__0() at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func1 compiler) at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func
1 compiler) 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.EntityQueryable1.GetAsyncEnumerator(CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.IncludableQueryable
2.GetAsyncEnumerator(CancellationToken cancellationToken) at System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable1.GetAsyncEnumerator() at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable
1 source, CancellationToken cancellationToken) at Stego.ReportPortal.Data.Services.Sections.OverdueAccountDataRepository.ListAsync(IUserInformation user, Nullable1 parentId) in C:\git\reportportal.api\Stego.ReportPortal.Data\Services\Sections\Financial\OverdueAccountDataRepository.cs:line 90 at Stego.ReportPortal.Controllers.Report.Sections.OverdueAcountController.Get(Int32 reportId) in C:\git\reportportal.api\Stego.MonthlyReports\Controllers\Report\Sections\OverdueAcountController.cs:line 45 at lambda_method(Closure , Object ) at Microsoft.Extensions.Internal.ObjectMethodExecutorAwaitable.Awaiter.GetResult() at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask
1 actionResultValueTask) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker) at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) at Stego.ReportPortal.Common.Filters.ExceptionFilterMiddleware.Invoke(HttpContext httpContext) in C:\git\reportportal.api\Stego.MonthlyReports\Common\Filters\ExceptionFilterMiddleware.cs:line 24 at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)`