Здравствуйте. Пишу реализацию динамической фильтрации и сортировки. Фильтрация работает, а вот при сортировке выбрасывается исключение:
System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
Данный код отлично работал на .NET Core 1.0 и .NET Core 1.1.
В качестве БД используется PostgreSQL и библиотека Npgsql.
Ниже представлен код.
Есть классы с параметрами сортировки:
SortDirection.cspublic enum SortDirection
{
Ascending=0,
Descending
}
SortExpression.cspublic class SortExpression<TEntity> where TEntity : class
{
public SortExpression(Expression<Func<TEntity, object>> sortBy, SortDirection sortDirection)
{
SortBy = sortBy;
SortDirection = sortDirection;
}
public Expression<Func<TEntity, object>> SortBy { get; set; }
public SortDirection SortDirection { get; set; }
}
И непосредственно класс, который содержит параметры динамической фильтрации:
Query.cspublic class Query<T> where T : class, IEntity
{
public Expression<Func<T,bool>> FilterExpression { get; set; }
public IList<SortExpression<T>> SortExpressions { get; set; }
public int? Skip { get; set; }
public int? Take { get; set; }
}
Код метода, который реализует динамическую фильтрацию и сортировку, представлен ниже:
IRepository.cspublic IEnumerable<T> Get(Query<T> request, IEnumerable<string> includes = null)
{
var result = new PagedEnumerable<T>();
IQueryable<T> query = _context.Set<T>().AsNoTracking();
if (request.FilterExpression != null)
{
query = query.Where(request.FilterExpression);
}
if (includes != null)
{
foreach (var include in includes)
query = query.Include(include);
}
var sortExpressions = request.SortExpressions;
if (sortExpressions != null && sortExpressions.Any())
{
IOrderedQueryable<T> orderedQuery = null;
for (var i = 0; i < sortExpressions.Count(); i++)
{
if (i == 0)
{
if (sortExpressions[i].SortDirection == SortDirection.Ascending)
{
orderedQuery = query.OrderBy(sortExpressions[i].SortBy);
}
else
{
orderedQuery = query.OrderByDescending(sortExpressions[i].SortBy);
}
}
else
{
if (sortExpressions[i].SortDirection == SortDirection.Ascending)
{
orderedQuery = orderedQuery.ThenBy(sortExpressions[i].SortBy);
}
else
{
orderedQuery = orderedQuery.ThenByDescending(sortExpressions[i].SortBy);
}
}
}
query = orderedQuery;
}
if (request.Skip.HasValue)
{
query = query.Skip(request.Skip.Value);
}
if (request.Take != null)
{
query = query.Take(request.Take.Value);
}
return query.AsEnumerable();
}
Полный стек-трейс исключения:
Stacktrace
System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
at System.ThrowHelper.ThrowArgumentOutOfRange_IndexException()
at System.Collections.Generic.List`1.get_Item(Int32 index)
at Microsoft.EntityFrameworkCore.Query.Expressions.SelectExpression.BindSubqueryProjectionIndex(Int32 projectionIndex, IQuerySource querySource)
at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.SqlTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Remotion.Linq.Parsing.ThrowingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.SqlTranslatingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitOrderByClause(OrderByClause orderByClause, QueryModel queryModel, Int32 index)
at Remotion.Linq.Clauses.OrderByClause.Accept(IQueryModelVisitor visitor, QueryModel queryModel, Int32 index)
at Remotion.Linq.QueryModelVisitorBase.VisitBodyClauses(ObservableCollection`1 bodyClauses, QueryModel queryModel)
at Remotion.Linq.QueryModelVisitorBase.VisitQueryModel(QueryModel queryModel)
at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.RelationalEntityQueryableExpressionVisitor.VisitSubQuery(SubQueryExpression expression)
at Remotion.Linq.Clauses.Expressions.SubQueryExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.ExpressionVisitorBase.VisitLambda[T](Expression`1 node)
at System.Linq.Expressions.Expression`1.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)
at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)
at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.RelationalEntityQueryableExpressionVisitor.VisitMethodCall(MethodCallExpression node)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at System.Dynamic.Utils.ExpressionVisitorUtils.VisitBlockExpressions(ExpressionVisitor visitor, BlockExpression block)
at System.Linq.Expressions.ExpressionVisitor.VisitBlock(BlockExpression node)
at System.Linq.Expressions.BlockExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.ExpressionVisitorBase.VisitLambda[T](Expression`1 node)
at System.Linq.Expressions.Expression`1.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)
at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)
at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.RelationalEntityQueryableExpressionVisitor.VisitMethodCall(MethodCallExpression node)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.ReplaceClauseReferences(Expression expression, IQuerySource querySource, Boolean inProjection)
at
Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitSelectClause(SelectClause selectClause, QueryModel queryModel)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitSelectClause(SelectClause selectClause, QueryModel queryModel)
at Remotion.Linq.Clauses.SelectClause.Accept(IQueryModelVisitor visitor, QueryModel queryModel)
at Remotion.Linq.QueryModelVisitorBase.VisitQueryModel(QueryModel queryModel)
at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.CreateQueryExecutor[TResult](QueryModel queryModel)
at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](QueryModel queryModel)
-— End of stack trace from previous location where exception was thrown —-
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](Expression query, INodeTypeProvider nodeTypeProvider, IDatabase database, IDiagnosticsLogger`1 logger, Type contextType)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass15_0`1.b__0()
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func`1 compiler)
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
at Remotion.Linq.QueryableBase`1.GetEnumerator()