-
-
Notifications
You must be signed in to change notification settings - Fork 450
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Compiled query that includes subclass throws exception #3464
Comments
Yes it's something that should work. It's much more likely that the issue is because of the |
@psampaio "Works on my box" This test passes in master: using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Marten;
using Marten.Linq;
using Marten.Testing.Harness;
using Xunit;
using Shouldly;
namespace DocumentDbTests.Bugs;
public class Bug_3464_Include_with_SingleOrDefault : BugIntegrationContext
{
[Fact]
public async Task can_make_the_query()
{
StoreOptions(opts =>
{
opts.Schema.For<OrderItem>().AddSubClass<Product>()
.AddSubClass<Subscription>();
});
var product = new Product();
theSession.Store(product);
var user = new User3464();
theSession.Store(user);
var order = new Order { UserId = user.Id, OrderItemId = product.Id };
theSession.Store(order);
await theSession.SaveChangesAsync();
IList<Product> orderItems = [];
IList<User3464> users = [];
var orderId = order.Id;
var order2 = await theSession.Query<Order>()
.Include(o => o.OrderItemId, orderItems)
.Include(o => o.UserId, users)
.SingleOrDefaultAsync(o => o.Id == orderId);
order2.ShouldNotBeNull();
orderItems.Single().Id.ShouldBe(product.Id);
users.Single().Id.ShouldBe(user.Id);
}
}
public class OrderDetails : ICompiledQuery<Order, Order?>
{
public Guid OrderId { get; init; }
public IList<OrderItem> OrderItems { get; } = [];
public IList<User3464> Users { get; } = [];
public Expression<Func<IMartenQueryable<Order>, Order?>> QueryIs()
{
return q => q
.Include(o => o.OrderItemId, OrderItems)
.Include(o => o.UserId, Users)
.SingleOrDefault(o => o.Id == OrderId);
}
}
public class Order
{
public Guid Id { get; set; }
public Guid OrderItemId { get; set; }
public Guid UserId { get; set; }
}
public class User3464
{
public Guid Id { get; set; }
}
public abstract class OrderItem
{
public Guid Id { get; set; }
}
public class Product: OrderItem
{
}
public class Subscription: OrderItem
{
} Can you spot anything different about what I'm doing compared to your code? |
And next time, please post the full stack trace |
You aren't maybe getting burned by having not migrated the database after adding the sub classing? Or stale generated code? Just not seeing anything wrong on my end. |
Sorry about that. I wanted to diagnose it myself before asking for more help, in case this was working as intended. I wasn't expecting you to proactively create a test for this. And I really appreciate it. Going back to the issue, your test actually fails if you replace the ad-hoc query: var order2 = await theSession.Query<Order>()
.Include(o => o.OrderItemId, orderItems)
.Include(o => o.UserId, users)
.SingleOrDefaultAsync(o => o.Id == orderId); with the compiled query: var query = new OrderDetails { OrderId = orderId };
var order2 = await theSession.QueryAsync(query);
orderItems = query.OrderItems.OfType<Product>().ToList();
users = query.Users.ToList(); Stack trace: System.IndexOutOfRangeException: Column must be between 0 and 1
System.IndexOutOfRangeException
Column must be between 0 and 1
at Npgsql.NpgsqlDataReader.ThrowColumnOutOfRange(Int32 maxIndex)
at Npgsql.NpgsqlDataReader.HandleInvalidState(ReaderState state, Int32 maxColumns)
at Npgsql.NpgsqlDataReader.<GetInfo>g__Slow|133_0(ColumnInfo& info, PgConverter& converter, Size& bufferRequirement, Boolean& asObject, <>c__DisplayClass133_0&)
at Npgsql.NpgsqlDataReader.GetFieldValueCore[T](Int32 ordinal)
at Npgsql.NpgsqlDataReader.GetFieldValueAsync[T](Int32 ordinal, CancellationToken cancellationToken)
at Marten.Generated.DocumentStorage.LightweightOrderItemSelector894903466.ResolveAsync(DbDataReader reader, CancellationToken token)
at Marten.Linq.Includes.IncludeReader`1.ReadAsync(DbDataReader reader, CancellationToken token) in /Users/psampaio/Projects/github/marten/src/Marten/Linq/Includes/IncludeReader.cs:line 35
at Marten.Linq.Includes.IncludeQueryHandler`1.HandleAsync(DbDataReader reader, IMartenSession session, CancellationToken token) in /Users/psampaio/Projects/github/marten/src/Marten/Linq/Includes/IncludeQueryHandler.cs:line 59
at Marten.Internal.Sessions.QuerySession.ExecuteHandlerAsync[T](IQueryHandler`1 handler, CancellationToken token) in /Users/psampaio/Projects/github/marten/src/Marten/Internal/Sessions/QuerySession.Execution.cs:line 100
at Marten.Internal.Sessions.QuerySession.ExecuteHandlerAsync[T](IQueryHandler`1 handler, CancellationToken token) in /Users/psampaio/Projects/github/marten/src/Marten/Internal/Sessions/QuerySession.Execution.cs:line 100
at Marten.Internal.Sessions.QuerySession.QueryAsync[TDoc,TOut](ICompiledQuery`2 query, CancellationToken token) in /Users/psampaio/Projects/github/marten/src/Marten/Internal/Sessions/QuerySession.Querying.cs:line 101
at DocumentDbTests.Bugs.Bug_3464_Include_with_SingleOrDefault.can_make_the_query() in /Users/psampaio/Projects/github/marten/src/DocumentDbTests/Bugs/Bug_3464_Include_with_SingleOrDefault.cs:line 45
at Xunit.Sdk.TestInvoker`1.<>c__DisplayClass46_0.<<InvokeTestMethodAsync>b__1>d.MoveNext() in /_/src/xunit.execution/Sdk/Frameworks/Runners/TestInvoker.cs:line 253
--- End of stack trace from previous location ---
at Xunit.Sdk.ExecutionTimer.AggregateAsync(Func`1 asyncAction) in /_/src/xunit.execution/Sdk/Frameworks/ExecutionTimer.cs:line 48
at Xunit.Sdk.ExceptionAggregator.RunAsync(Func`1 code) in /_/src/xunit.core/Sdk/ExceptionAggregator.cs:line 90 I'm going to look into the other tests to see if I can figure it out. |
TBH, should that compiled query even work? I can't debug into the IncludeReader generation (dynamic code?), but I wouldn't expect it to add a reader for all subclasses, if that even makes sense? I also tried changing the compiled query to be generic, and the correct IncludeReader is used, but I get the same error. |
I have the following query working:
where
Product
derives from the abstractOrderItem
. It's registered as:I converted it to the following compiled query:
This throws
System.IndexOutOfRangeException: Column must be between 0 and 1
. I've also tried this making the compiled query generic, constraining the OrderItem list (I usually know the specific type when querying) and get the same exception.My guess is that somewhere in the chain
IncludeQueryHandler
>IncludeReader
>CastingSelector
, it's missing the right type to load, but I can't find where that is.Before I try to dig a bit deeper, is this something that should work?
The text was updated successfully, but these errors were encountered: