Repository navigation
Projection cause "Index out of range" on Database first EF core (net 6) #5229
Description
Is there an existing issue for this?
- I have searched the existing issues
Describe the bug
I Have wrapped an old DB2 database with EF and created a DbContext which does not match the table schema on the database.
I had to "split" tables in different entities using the "Owned" properties
so namely the table Viaggi is splitted in infoPax, infoMerci, and so on.
for each of the owned type I created a Owned navigation property using EF
for example here entity is of Type Viaggio
_ = entity.OwnsOne(via => via.InfoPax, entity =>
{
_ = entity.Property(e => e.Capacita).HasColumnName("VIPAT").HasColumnType("smallint(2)").HasDefaultValueSql("0");
_ = entity.Property(e => e.Venduto).HasColumnName("VIPAV").HasColumnType("smallint(2)").HasDefaultValueSql("0");
_ = entity.Property(e => e.Warning).HasColumnName("VIPAW").HasColumnType("smallint(2)").HasDefaultValueSql("0");
_ = entity.Property(e => e.BloccoVendite).IsRequired().HasColumnName("VIPBV").HasColumnType("char(1)").HasDefaultValueSql("' '");
_ = entity.Property(e => e.Abilitazione).IsRequired().HasColumnName("VIPFV").HasColumnType("char(1)").HasDefaultValueSql("' '");
_ = entity.Property(e => e.TotaleMetriLieari).HasColumnName("VIPML").HasColumnType("decimal(5, 1)").HasDefaultValueSql("0");
_ = entity.Property(e => e.ProgressivoBooking).HasColumnName("VIPPB").HasColumnType("integer(4)").HasDefaultValueSql("0");
}I Have the usual repository accessing the data and returning an IQueryable<Viaggio>
If I don't use Projections everything works great.
The problem starts when I add [UseProjection] on my query: It all works well until I try to access those owned (in theory non nullable) owned entities which really are in the same table of Viaggi.
That causes
"Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')",
I had a look in the produced Linq query :
Compiling query expression:
'DbSet<Viaggio>()
.Where(x => x.IdViaggio == __id_0)
.Select(_s1 => new Viaggio{
IdSocieta = _s1.IdSocieta,
InfoPax = _s1.InfoPax != null ? new InfoPax{ BloccoVendite = _s1.InfoPax.BloccoVendite }
: null,
)
.ToList()
}
)'
and it looks fine but :
- it appears that the check
_s1.InfoPax != null ?is causing the index out of range problem. If I remove the null check and the ternary operator it works and produces the rightSQL
Steps to reproduce
- Using Db First approach create a table on a server and map it onto different entities using ef core table splitting https://docs.microsoft.com/en-us/ef/core/modeling/table-splitting
- try to access the nested owned entities using a query in graphql
Relevant log output
"errors": [
{
"message": "Unexpected Execution Error",
"locations": [
{
"line": 2,
"column": 2
}
],
"path": [
"viaggiProjection"
],
"extensions": {
"message": "Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')",
"stackTrace": " at Microsoft.EntityFrameworkCore.Query.SqlExpressions.SelectExpression.GetProjection(ProjectionBindingExpression projectionBindingExpression)\n at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.VisitExtension(Expression extensionExpression)\n at System.Linq.Expressions.Expression.Accept(ExpressionVisitor visitor)\n at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)\n at System.Linq.Expressions.ExpressionVisitor.VisitMemberAssignment(MemberAssignment node)\n at System.Linq.Expressions.ExpressionVisitor.VisitMemberBinding(MemberBinding node)\n at System.Linq.Expressions.ExpressionVisitor.Visit[T](ReadOnlyCollection`1 nodes, Func`2 elementVisitor)\n at System.Linq.Expressions.ExpressionVisitor.VisitMemberInit(MemberInitExpression node)\n at System.Linq.Expressions.MemberInitExpression.Accept(ExpressionVisitor visitor)\n at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ProcessShaper(Expression shaperExpression, RelationalCommandCache& relationalCommandCache, LambdaExpression& relatedDataLoaders, Int32& collectionId)\n at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.VisitShapedQuery(ShapedQueryExpression shapedQueryExpression)\n at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.VisitExtension(Expression extensionExpression)\n at System.Linq.Expressions.Expression.Accept(ExpressionVisitor visitor)\n at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)\n at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)\n at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)\n at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)\n at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)\n at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetAsyncEnumerator(CancellationToken cancellationToken)\n at System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1.GetAsyncEnumerator()\n at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)\n at HotChocolate.Data.ToListMiddleware`1.InvokeAsync(IMiddlewareContext context)\n at HotChocolate.Types.EntityFrameworkObjectFieldDescriptorExtensions.<>c__DisplayClass2_1`1.<<UseDbContext>b__4>d.MoveNext()\n--- End of stack trace from previous location ---\n at HotChocolate.Types.EntityFrameworkObjectFieldDescriptorExtensions.<>c__DisplayClass2_1`1.<<UseDbContext>b__4>d.MoveNext()\n--- End of stack trace from previous location ---\n at HotChocolate.Execution.Processing.Tasks.ResolverTask.ExecuteResolverPipelineAsync(CancellationToken cancellationToken)\n at HotChocolate.Execution.Processing.Tasks.ResolverTask.TryExecuteAsync(CancellationToken cancellationToken)"
}
}
]
}Additional Context?
Im using IBM entity framework core to connect to an AS400 system which has a DB2 instance
Product
Hot Chocolate
Version
12.12.0
Activity
PascalSenn commentedon Jul 12, 2022
@invzz thanks for reporting. We are working on a better ef core integration. At the moment we do not know if EF Core (and what Features of EF Core) is used.
invzz commentedon Jul 12, 2022
@PascalSenn thanks for your reply, I'm looking forward to it. My workaround is to work with flattened tables without tablesplitting and use automapper later to get the right entity subdivision.
PascalSenn commentedon Jul 12, 2022
ah you use Automapper? because then this is probably the issue
invzz commentedon Jul 13, 2022
I'm not using Automapper in graphQL, although I have it registered in services and I use it for other endpoints in a controller which expose some other pieces of functionality (basic crud db interrogations)
I also tried to exclude Automapper ( deleting the
.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies())line) from the loaded services and excluding it from my controller, but I had the same resultsAnother "weird" and related thing is happening :
I changed my context and started using flattened tables which models mirrors the tables in the db schema:
Where the
buildModelmethod is a static method which for every property adds the configurationIn this way I though to avoid using those owned types and table splitting approach.
My query class is a simple one:
ViaggiProjection) any property insideNavewhich have Many-to-1 relation with shadowed navigation property on One side I get that index out of range and the.Select(_s1 => new ViaggioGviat{ Nave = _s1.Nave != null ? new NaveTanav{ IdNave = _s1.Nave.IdNave } : null } )expression (which causes the error)results in error
{ "errors": [ { "message": "Unexpected Execution Error", "locations": [ { "line": 2, "column": 3 } ], "path": [ "viaggiProjection" ], "extensions": { "message": "Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')", "stackTrace": " at Microsoft.EntityFrameworkCore.Query.SqlExpressions.SelectExpression.GetProjection(ProjectionBindingExpression projectionBindingExpression)\n at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.VisitExtension(Expression extensionExpression)\n at System.Linq.Expressions.Expression.Accept(ExpressionVisitor visitor)\n at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)\n at System.Linq.Expressions.ExpressionVisitor.VisitBinary(BinaryExpression node)\n at System.Linq.Expressions.BinaryExpression.Accept(ExpressionVisitor visitor)\n at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)\n at System.Linq.Expressions.ExpressionVisitor.VisitConditional(ConditionalExpression node)\n at System.Linq.Expressions.ConditionalExpression.Accept(ExpressionVisitor visitor)\n at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)\n at System.Linq.Expressions.ExpressionVisitor.VisitMemberAssignment(MemberAssignment node)\n at System.Linq.Expressions.ExpressionVisitor.VisitMemberBinding(MemberBinding node)\n at System.Linq.Expressions.ExpressionVisitor.Visit[T](ReadOnlyCollection`1 nodes, Func`2 elementVisitor)\n at System.Linq.Expressions.ExpressionVisitor.VisitMemberInit(MemberInitExpression node)\n at System.Linq.Expressions.MemberInitExpression.Accept(ExpressionVisitor visitor)\n at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ProcessShaper(Expression shaperExpression, RelationalCommandCache& relationalCommandCache, LambdaExpression& relatedDataLoaders, Int32& collectionId)\n at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.VisitShapedQuery(ShapedQueryExpression shapedQueryExpression)\n at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.VisitExtension(Expression extensionExpression)\n at System.Linq.Expressions.Expression.Accept(ExpressionVisitor visitor)\n at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)\n at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)\n at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)\n at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)\n at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)\n at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetAsyncEnumerator(CancellationToken cancellationToken)\n at System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1.GetAsyncEnumerator()\n at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)\n at HotChocolate.Data.ToListMiddleware`1.InvokeAsync(IMiddlewareContext context)\n at HotChocolate.Types.EntityFrameworkObjectFieldDescriptorExtensions.<>c__DisplayClass2_1`1.<<UseDbContext>b__4>d.MoveNext()\n--- End of stack trace from previous location ---\n at HotChocolate.Types.EntityFrameworkObjectFieldDescriptorExtensions.<>c__DisplayClass2_1`1.<<UseDbContext>b__4>d.MoveNext()\n--- End of stack trace from previous location ---\n at HotChocolate.Execution.Processing.Tasks.ResolverTask.ExecuteResolverPipelineAsync(CancellationToken cancellationToken)\n at HotChocolate.Execution.Processing.Tasks.ResolverTask.TryExecuteAsync(CancellationToken cancellationToken)" } } ] }caused by the generated linq expression using
projectionswhile the
works and reply
everything works if I don't use projections as in
GetFullViaggi.In My use case projections are necessary because the entities have 200+ fields, queries with few fields are much faster (lower in volume: for 1 full viaggio query i get 6 MB of data, if I use projections i get few kb)
for clarity I here the navigation properties inside
viaggioGviatI'm now trying to use the github repo instead of the nuget packages so I can further investigate through brakepoints what's happening, Hotchocolate project is huge and I'm not currently been able to set it up as I get some reference errors on builds
invzz commentedon Jul 13, 2022
@PascalSenn
looks like my problem is here
Looks like the
NotNullAndAlsois adding the condition which causes my problems:return Expression.Default(property.Type));I kinda solved all my problems and works like a charm. I don't know if this might help. Thanksmichaelstaib commentedon Feb 25, 2026
Hey,
I have tested this on main.
Current main commit:
f64f691347.What I tested:
Result: