marten icon indicating copy to clipboard operation
marten copied to clipboard

Selecting JObject => System.IndexOutOfRangeException

Open srasch opened this issue 2 years ago • 0 comments

Hi there,

I'm upgrading Marten from 3.14.3 to 5.8.0 and I'm running in an Exception when my document contains a JObject. When there is no Select-Clause (the full document is returned) the data is fine. But when the Select-Clause contains the JObject-Property it throws an IndexOutOfRangeException.

System.IndexOutOfRangeException: Index was outside the bounds of the array.

System.IndexOutOfRangeException
Index was outside the bounds of the array.
   at Marten.Linq.Fields.DictionaryField..ctor(String dataLocator, Casing casing, EnumStorage enumStorage, MemberInfo[] members)
   at Marten.Linq.Fields.FieldMapping.createFieldByFieldType(MemberInfo[] members, Type fieldType)
   at Marten.Linq.Fields.FieldMapping.resolveField(MemberInfo[] members)
   at Marten.Linq.Fields.FieldMapping.<>c__DisplayClass19_0.<FieldFor>b__0(String _)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Marten.Linq.Fields.FieldMapping.FieldFor(MemberInfo member)
   at Marten.Linq.Fields.FieldMapping.FieldFor(IEnumerable`1 members)
   at Marten.Linq.Parsing.SelectTransformBuilder.TargetObject.SetterBinding.ToJsonBuildObjectPair(IFieldMapping mapping, ISerializer serializer)
   at Marten.Linq.Parsing.SelectTransformBuilder.TargetObject.<>c__DisplayClass6_0.<ToSelectField>b__0(SetterBinding x)
   at System.Linq.Enumerable.SelectListIterator`2.ToArray()
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at Baseline.GenericEnumerableExtensions.Join(IEnumerable`1 values, String separator)
   at Marten.Linq.Parsing.SelectTransformBuilder.TargetObject.ToSelectField(IFieldMapping fields, ISerializer serializer)
   at Marten.Linq.Parsing.SelectTransformBuilder..ctor(Expression clause, IFieldMapping fields, ISerializer serializer)
   at Marten.Linq.SqlGeneration.SelectorStatement.ToSelectTransform(Expression selectExpression, ISerializer serializer)
   at Marten.Linq.Parsing.LinqHandlerBuilder.SelectorVisitor.VisitNew(NewExpression node)
   at System.Linq.Expressions.NewExpression.Accept(ExpressionVisitor visitor)
   at Marten.Linq.Parsing.LinqHandlerBuilder.readQueryModel(QueryModel queryModel, IDocumentStorage storage, Boolean considerSelectors, IFieldMapping fields)
   at Marten.Linq.Parsing.LinqHandlerBuilder..ctor(MartenLinqQueryProvider provider, IMartenSession session, Expression expression, ResultOperatorBase additionalOperator, Boolean forCompiled)
   at Marten.Linq.MartenLinqQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken token)
   at nwp.database.testing.queries.SelectWithJObject.test() in B:\Projekte\winplan\backend\.tests\database.testing\queries\Foo.cs:line 57
   at Xunit.Sdk.TestInvoker`1.<>c__DisplayClass48_1.<<InvokeTestMethodAsync>b__1>d.MoveNext() in C:\Dev\xunit\xunit\src\xunit.execution\Sdk\Frameworks\Runners\TestInvoker.cs:line 264
--- End of stack trace from previous location ---
   at Xunit.Sdk.ExecutionTimer.AggregateAsync(Func`1 asyncAction) in C:\Dev\xunit\xunit\src\xunit.execution\Sdk\Frameworks\ExecutionTimer.cs:line 48
   at Xunit.Sdk.ExceptionAggregator.RunAsync(Func`1 code) in C:\Dev\xunit\xunit\src\xunit.core\Sdk\ExceptionAggregator.cs:line 90

This is my test-case:

public class SelectWithJObject : BugIntegrationContext
{
  [DebugFact]
  public async Task test()
  {
    StoreOptions(_ =>
                 {
                   _.Schema.For<TestReadModel>()
                     .Identity(x => x.InstanceId);
                   _.UseNodaTime();
                 });

    var e = new
    {
      Id = Guid.NewGuid(),
    };

    var test1 = new TestReadModel
    {
      InstanceId = e.Id,
      Status = "progress",
      InstanceData = JObject.FromObject(new { Data = "Pew Pew", }),
      CreatedAt = SystemClock.Instance.GetCurrentInstant(),
    };


    using (var session = theStore.LightweightSession())
    {
      session.Store(test1);
      await session.SaveChangesAsync(default);
    }

    using (var session = theStore.QuerySession())
    {
      var instanceFilesTask = await session.Query<TestReadModel>()
                                .Where(x => x.InstanceId == e.Id)
                                .Select(x => new { x.InstanceData, x.Status, x.InstanceId, })
                                .ToListAsync(default);

      instanceFilesTask.Count.ShouldBePositive();
      instanceFilesTask.First().InstanceData["Data"].ShouldBe("Pew Pew");
    }
  }
}

public class TestReadModel
{
  public Guid InstanceId { get; set; }
  public string Status { get; set; }
  public Instant CreatedAt { get; set; }
  public JObject InstanceData { get; set; }
}

Any hints on this?

srasch avatar Jul 28 '22 07:07 srasch