dotnet / efcore

EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
https://docs.microsoft.com/ef/
MIT License
13.77k stars 3.18k forks source link

Enumerable depth #30042

Open GLuca74 opened 1 year ago

GLuca74 commented 1 year ago

Hello,

having this model:

    public class Continent
    {
        public Guid ContinentID { get; set; }
        public string ContinentName { get; set; }
        public virtual ICollection<Nation> Nations { get; set; }
    }

    public class Nation
    {
        public Guid NationID { get; set; }
        public string NationName { get; set; }
        public virtual Continent Continent { get; set; }
        public virtual ICollection<City> Cities { get; set; }
    }

    public class City
    {
        public Guid CityID { get; set; }
        public virtual Nation Nation { get; set; }
        public string CityName { get; set; }
        public virtual ICollection<District> Districts { get; set; }
    }

    public class District
    {
        public Guid DistrictID { get; set; }
        public string DistrictName { get; set; }
        public virtual City City { get; set; }
        public virtual ICollection<Street> Streets { get; set; }
    }

    public class Street
    {
        public Guid StreetID { get; set; }
        public string StreetName { get; set; }
        public virtual District District { get; set; }
    }

this query

ctx.Set<Continent>().Select(c => c.Nations.Select(n=> n.Cities.Select(c => c.Districts))).ToArray(); works, but if I add another step

ctx.Set<Continent>().Select(c => c.Nations.Select(n=> n.Cities.Select(c => c.Districts.Select(d => d.Streets)))).ToArray(); fails with :

System.ArgumentException
  HResult=0x80070057
  Messaggio=GenericArguments[2], 'System.Collections.Generic.List`1[System.Collections.Generic.List`1[System.Collections.Generic.ICollection`1[ConsoleApp1.Street]]]', 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'.
  Origine=System.Private.CoreLib
  Analisi dello stack:
   in System.RuntimeType.ValidateGenericArguments(MemberInfo definition, RuntimeType[] genericArguments, Exception e)
   in System.Reflection.RuntimeMethodInfo.MakeGenericMethod(Type[] methodInstantiation)
   in Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.VisitExtension(Expression extensionExpression)
   in System.Linq.Expressions.Expression.Accept(ExpressionVisitor visitor)
   in Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ProcessShaper(Expression shaperExpression, RelationalCommandCache& relationalCommandCache, LambdaExpression& relatedDataLoaders, Int32& collectionId)
   in Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.VisitShapedQuery(ShapedQueryExpression shapedQueryExpression)
   in Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.VisitExtension(Expression extensionExpression)
   in System.Linq.Expressions.Expression.Accept(ExpressionVisitor visitor)
   in System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   in Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
   in Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass9_0`1.<Execute>b__0()
   in Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
   in Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
   in Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetEnumerator()
   in System.Collections.Generic.LargeArrayBuilder`1.AddRange(IEnumerable`1 items)
   in System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable`1 source)
   in System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   in ConsoleApp1.Program.Main(String[] args) in C:\EFError\ConsoleApp1\ConsoleApp1\Program.cs: riga 17

VerificationException: Method Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor+ShaperProcessingExpressionVisitor.PopulateCollection: type argument 'System.Collections.Generic.List`1[System.Collections.Generic.List`1[System.Collections.Generic.ICollection`1[ConsoleApp1.Street]]]' violates the constraint of type parameter 'TRelatedEntity'.

Provider : Microsoft.EntityFrameworkCore.SqlServer 6.0.13

ConsoleApp1.zip

ajcvickers commented 1 year ago

Note for triage: Method signature is:

private static void PopulateCollection<TCollection, TElement, TRelatedEntity>(...)
    where TRelatedEntity : TElement
    where TCollection : class, ICollection<TElement>

Generic types are:

TCollection: List<List<IQueryable<ICollection<Street>>>>
TElement: List<List<ICollection<Street>>>
TRelatedEntity: List<IQueryable<ICollection<Street>>>

Looks like the IQueryable has not been appropriately replaced.