zzzprojects / EntityFramework-Plus

Entity Framework Plus extends your DbContext with must-haves features: Include Filter, Auditing, Caching, Query Future, Batch Delete, Batch Update, and more
https://entityframework-plus.net/
MIT License
2.27k stars 318 forks source link

IncludeOptimizedByPathIssue throw error #771

Open v-karnaukhov opened 1 year ago

v-karnaukhov commented 1 year ago

Description

IncludeOptimizedByPathIssue throw error

"Method Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor+ShaperProcessingExpressionVisitor.PopulateCollection: type argument 'System.Collections.Generic.List1[System.Collections.Generic.List1[IssueWithAnyAll.Entities.File]]' violates the constraint of type parameter 'TRelatedEntity'."

Exact that code perfectly worked for EF 6, but now after upgrading to EF Core 7 it produce error.

In reproducing repo you can see this :

 var temp = context.Requests
        .Where(x => x.Id == 1)
        .IncludeOptimizedMultiple(votesIncludes)
        .FirstOrDefault();

where IncludeOptimizedMultiple is extension :

public static IQueryable<TEntity> IncludeOptimizedMultiple<TEntity>(
        this IQueryable<TEntity> query,
        IEnumerable<string> includes) where TEntity : class
    {
        if (includes != null)
        {
            query = includes.Aggregate(query, (current, include) => current.IncludeOptimizedByPath(include));
        }

        return query;
    }

Exception

Exception message:
Method Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor+ShaperProcessingExpressionVisitor.PopulateCollection: type argument 'System.Collections.Generic.List`1[System.Collections.Generic.List`1[IssueWithAnyAll.Entities.File]]' violates the constraint of type parameter 'TRelatedEntity'.

Stack trace:
GenericArguments[2], 'System.Collections.Generic.List`1[System.Collections.Generic.List`1[IssueWithAnyAll.Entities.File]]', on 'Void PopulateCollection[TCollection,TElement,TRelatedEntity](Int32, Microsoft.EntityFrameworkCore.Query.QueryContext, System.Data.Common.DbDataReader, Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryResultCoordinator, System.Func`3[Microsoft.EntityFrameworkCore.Query.QueryContext,System.Data.Common.DbDataReader,System.Object[]], System.Func`3[Microsoft.EntityFrameworkCore.Query.QueryContext,System.Data.Common.DbDataReader,System.Object[]], System.Func`3[Microsoft.EntityFrameworkCore.Query.QueryContext,System.Data.Common.DbDataReader,System.Object[]], System.Collections.Generic.IReadOnlyList`1[Microsoft.EntityFrameworkCore.ChangeTracking.ValueComparer], System.Collections.Generic.IReadOnlyList`1[Microsoft.EntityFrameworkCore.ChangeTracking.ValueComparer], System.Collections.Generic.IReadOnlyList`1[Microsoft.EntityFrameworkCore.ChangeTracking.ValueComparer], System.Func`5[Microsoft.EntityFrameworkCore.Query.QueryContext,System.Data.Common.DbDataReader,Microsoft.EntityFrameworkCore.Query.Internal.ResultContext,Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryResultCoordinator,TRelatedEntity])' violates the constraint of type 'TRelatedEntity'.

Project

Reproducing repo is here : https://github.com/v-karnaukhov/z.entityframework.plus.issue. In repo you can find script for creating db structure (DB Scripts folder).

Further technical details

JonathanMagnan commented 1 year ago

Hello @v-karnaukhov ,

Unfortunately, even if we learned a lot from this issue, we didn't succeed in fixing it.

You can still achieve this by performing a LINQ on your side:

var temp = context.Requests
    .Where(x => x.Id == 1)
    .IncludeOptimizedByPath($"{nameof(Request.Meetings)}.{nameof(MeetingRequest.Votes)}.{nameof(Vote.Documents)}")
    .IncludeOptimized(x => x.Meetings.SelectMany(x => x.Votes.SelectMany(x => x.Documents).Select(x => x.File)))
    .FirstOrDefault();

Only the second IncludeOptimized was not working to File not being a collection.

At this moment, we will not try deeper to fix it as we currently don't progress anymore on it. We simply don't know how to fix it.

Best Regards,

Jon