dataobjects-net
dataobjects-net copied to clipboard
Unable to translate exception on query grouped by LinqExtension field
DO 7.0.3
Fail to execute query that contains > 1 aggregate value by field with link access inside lambda expression
Code sample
using System.Linq.Expressions;
using DoTest;
using Microsoft.Data.SqlClient;
using Xtensive.Orm;
using Xtensive.Orm.Configuration;
internal class Program
{
private static async Task Main(string[] args)
{
try
{
DbHelper.ExecuteNonQuery("DROP DATABASE [DO-Tests]");
}
catch (Exception)
{
}
DbHelper.ExecuteNonQuery("CREATE DATABASE [DO-Tests]");
var dc = new DomainConfiguration("sqlserver", new SqlConnectionStringBuilder(DbHelper.ConnectionString()).ToString());
dc.Sessions.Add(new SessionConfiguration(WellKnown.Sessions.Default) { BatchSize = 25 });
dc.Types.Register(typeof(TestEntity));
dc.Types.Register(typeof(LinkEntity));
Expression<Func<TestEntity, decimal?>> lambdaExpression = it => it.Link.Value;
dc.LinqExtensions.Register(typeof(TestEntity).GetProperty(nameof(TestEntity.CalculatedValue)), lambdaExpression);
dc.UpgradeMode = DomainUpgradeMode.Recreate;
await using var d = await Domain.BuildAsync(dc);
await using var s = await d.OpenSessionAsync();
await using var t = await s.OpenTransactionAsync();
// OK
_ = s.Query.All<TestEntity>()
.GroupBy(it => new
{
Name = it.Name == null
? string.Empty
: it.Name
}).Select(it => new
{
GroupCount = it.Count(),
it.Key,
ValueCalculated_Min = it.Min(e => e.CalculatedValue)
}).Select(it => new
{
it.Key.Name,
Id = Guid.NewGuid(),
_Count = it.GroupCount,
it.ValueCalculated_Min
})
.ToArray();
// OK
_ = s.Query.All<TestEntity>()
.GroupBy(it => new
{
Name = it.Name == null
? string.Empty
: it.Name
}).Select(it => new
{
GroupCount = it.Count(),
it.Key,
ValueCalculated_Min = it.Max(e => e.CalculatedValue)
}).Select(it => new
{
it.Key.Name,
Id = Guid.NewGuid(),
_Count = it.GroupCount,
it.ValueCalculated_Min
})
.ToArray();
// OK
_ = s.Query.All<TestEntity>()
.GroupBy(it => new
{
Name = it.Name == null
? string.Empty
: it.Name
}).Select(it => new
{
GroupCount = it.Count(),
it.Key,
ValueCalculated_Min = it.Min(e => e.CalculatedValue),
ValueCalculated_Max = it.Max(e => e.CalculatedValue),
Count = it.Count(e => e.Link != null)
}).Select(it => new
{
it.Key.Name,
Id = Guid.NewGuid(),
_Count = it.GroupCount,
it.ValueCalculated_Min,
it.ValueCalculated_Max,
it.Count
})
.ToArray();
// OK
_ = s.Query.All<TestEntity>()
.GroupBy(it => new
{
Name = it.Name == null
? string.Empty
: it.Name
}).Select(it => new
{
GroupCount = it.Count(),
it.Key,
ValueCalculated_Min = it.Min(e => e.Link.Value - e.Value),
ValueCalculated_Max = it.Max(e => e.Link.Value - e.Value)
}).Select(it => new
{
it.Key.Name,
Id = Guid.NewGuid(),
_Count = it.GroupCount,
it.ValueCalculated_Min,
it.ValueCalculated_Max
})
.ToArray();
// FAIL
_ = s.Query.All<TestEntity>()
.GroupBy(it => new
{
Name = it.Name == null
? string.Empty
: it.Name
}).Select(it => new
{
GroupCount = it.Count(),
it.Key,
ValueCalculated_Min = it.Min(e => e.CalculatedValue),
ValueCalculated_Max = it.Max(e => e.CalculatedValue)
}).Select(it => new
{
it.Key.Name,
Id = Guid.NewGuid(),
_Count = it.GroupCount,
it.ValueCalculated_Min,
it.ValueCalculated_Max
})
.ToArray();
}
[HierarchyRoot]
public class LinkEntity : Entity
{
public LinkEntity(Session session) : base(session)
{
}
[Key] [Field(Nullable = false)] public int Id { get; set; }
[Field] public decimal? Value { get; set; }
}
[HierarchyRoot]
public class TestEntity : Entity
{
public TestEntity(Session session) : base(session)
{
}
[Key] [Field(Nullable = false)] public int Id { get; set; }
[Field] public string Name { get; set; }
[Field] public LinkEntity Link { get; set; }
[Field(Nullable = true)] public decimal? Value { get; set; }
public decimal? CalculatedValue { get; set; }
}
}
Exception
Unhandled exception. Xtensive.Orm.QueryTranslationException: Unable to translate 'Query.All().GroupBy(it => new @<Name>((it.Name == null)
? .Empty
: it.Name)).Select(it => new @<GroupCount, Key, ValueCalculated_Min, ValueCalculated_Max>(
it.Count(),
it.Key,
it.Min(e => e.CalculatedValue),
it.Max(e => e.CalculatedValue)
)).Select(it => new @<Name, Id, _Count, ValueCalculated_Min, ValueCalculated_Max>(
it.Key.Name,
Guid.NewGuid(),
it.GroupCount,
it.ValueCalculated_Min,
it.ValueCalculated_Max
))' expression. See inner exception for details.
---> System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')
at System.Collections.Generic.List`1.get_Item(Int32 index)
at Xtensive.Orm.Rse.Providers.AggregateProvider..ctor(CompilableProvider source, Int32[] groupIndexes, AggregateColumnDescriptor[] columnDescriptors)
at Xtensive.Orm.Linq.Translator.VisitAggregate(Expression source, MethodInfo method, LambdaExpression argument, Boolean isRoot, MethodCallExpression expressionPart)
at Xtensive.Orm.Linq.Translator.VisitQueryableMethod(MethodCallExpression mc, QueryableMethodKind methodKind)
at Xtensive.Linq.QueryableVisitor.VisitMethodCall(MethodCallExpression mc)
at Xtensive.Orm.Linq.Translator.VisitMethodCall(MethodCallExpression mc)
at Xtensive.Linq.ExpressionVisitor`1.Visit(Expression e)
at Xtensive.Orm.Linq.Translator.Visit(Expression e)
at Xtensive.Orm.Linq.Translator.VisitNewExpressionArguments(NewExpression n)
at Xtensive.Orm.Linq.Translator.VisitNew(NewExpression newExpression)
at Xtensive.Linq.ExpressionVisitor`1.Visit(Expression e)
at Xtensive.Orm.Linq.Translator.Visit(Expression e)
at Xtensive.Orm.Linq.Translator.VisitLambda(LambdaExpression le)
at Xtensive.Orm.Linq.Translator.BuildProjection(LambdaExpression le)
at Xtensive.Orm.Linq.Translator.VisitSelect(Expression expression, LambdaExpression le)
at Xtensive.Orm.Linq.Translator.VisitQueryableMethod(MethodCallExpression mc, QueryableMethodKind methodKind)
at Xtensive.Linq.QueryableVisitor.VisitMethodCall(MethodCallExpression mc)
at Xtensive.Orm.Linq.Translator.VisitMethodCall(MethodCallExpression mc)
at Xtensive.Linq.ExpressionVisitor`1.Visit(Expression e)
at Xtensive.Orm.Linq.Translator.Visit(Expression e)
at Xtensive.Orm.Linq.Translator.VisitSequence(Expression sequenceExpression, Expression expressionPart)
at Xtensive.Orm.Linq.Translator.VisitSequence(Expression sequenceExpression)
at Xtensive.Orm.Linq.Translator.VisitSelect(Expression expression, LambdaExpression le)
at Xtensive.Orm.Linq.Translator.VisitQueryableMethod(MethodCallExpression mc, QueryableMethodKind methodKind)
at Xtensive.Linq.QueryableVisitor.VisitMethodCall(MethodCallExpression mc)
at Xtensive.Orm.Linq.Translator.VisitMethodCall(MethodCallExpression mc)
at Xtensive.Linq.ExpressionVisitor`1.Visit(Expression e)
at Xtensive.Orm.Linq.Translator.Visit(Expression e)
at Xtensive.Orm.Linq.Translator.Translate()
at Xtensive.Orm.Linq.QueryProvider.Translate(Expression expression, CompilerConfiguration compilerConfiguration)
--- End of inner exception stack trace ---
at Xtensive.Orm.Linq.QueryProvider.Translate(Expression expression, CompilerConfiguration compilerConfiguration)
at Xtensive.Orm.Linq.QueryProvider.Translate(Expression expression)
at Xtensive.Orm.Linq.QueryProvider.Execute[TResult](Expression expression, Func`4 runQuery)
at Xtensive.Orm.Linq.QueryProvider.ExecuteSequence[T](Expression expression)
at Xtensive.Orm.Linq.Queryable`1.GetEnumerator()
at System.Collections.Generic.LargeArrayBuilder`1.AddRange(IEnumerable`1 items)
at System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at Program.Main(String[] args) in /Users/anton.guschin/RiderProjects/DoTest/DoTest/Program.cs:line 108
at Program.Main(String[] args) in /Users/anton.guschin/RiderProjects/DoTest/DoTest/Program.cs:line 108
at Program.Main(String[] args) in /Users/anton.guschin/RiderProjects/DoTest/DoTest/Program.cs:line 108
at Program.Main(String[] args) in /Users/anton.guschin/RiderProjects/DoTest/DoTest/Program.cs:line 108
at Program.<Main>(String[] args)