Метод 'OrderBy' должен быть вызван до исключения метода 'Пропустить'

Я пытался реализовать jQgrid с помощью MvcjQgrid и я получил это исключение.

System.NotSupportedException was unhandled by user code
  Message=The method 'Skip' is only supported for sorted input in LINQ to Entities. The method 'OrderBy' must be called before the method 'Skip'.

Хотя OrdeyBy используется до метода Skip, почему он генерирует исключение? Как это можно решить?

Я столкнулся с исключением в контроллере:

public ActionResult GridDataBasic(GridSettings gridSettings)
        {          
            var jobdescription = sm.GetJobDescription(gridSettings);
            var totalJobDescription = sm.CountJobDescription(gridSettings);

            var jsonData = new
            {
                total = totalJobDescription / gridSettings.PageSize + 1,
                page = gridSettings.PageIndex,
                records = totalJobDescription,
                rows = (
                    from j in jobdescription
                    select new
                    {
                        id = j.JobDescriptionID,
                        cell = new[] 
                    { 
                        j.JobDescriptionID.ToString(), 
                        j.JobTitle,
                        j.JobType.JobTypeName,
                        j.JobPriority.JobPriorityName,
                        j.JobType.Rate.ToString(),
                        j.CreationDate.ToShortDateString(),
                         j.JobDeadline.ToShortDateString(),

                    }
                    }).ToArray()
            };
            return Json(jsonData, JsonRequestBehavior.AllowGet);
        }

Метод GetJobDescription и Метод CountJobDescription

public int CountJobDescription(GridSettings gridSettings)
        {
            var jobdescription = _dataContext.JobDescriptions.AsQueryable();

            if (gridSettings.IsSearch)
            {
                jobdescription = gridSettings.Where.rules.Aggregate(jobdescription, FilterJobDescription);
            }
            return jobdescription.Count();
        }

        public IQueryable<JobDescription> GetJobDescription(GridSettings gridSettings)
        {
            var jobdescription = orderJobDescription(_dataContext.JobDescriptions.AsQueryable(), gridSettings.SortColumn, gridSettings.SortOrder);

            if (gridSettings.IsSearch)
            {
                jobdescription = gridSettings.Where.rules.Aggregate(jobdescription, FilterJobDescription);
            }

            return jobdescription.Skip((gridSettings.PageIndex - 1) * gridSettings.PageSize).Take(gridSettings.PageSize);
        }

И, наконец, FilterJobDescription и OrderJobDescription

private static IQueryable<JobDescription> FilterJobDescription(IQueryable<JobDescription> jobdescriptions, Rule rule)
        {
            if (rule.field == "JobDescriptionID")
            {
                int result;
                if (!int.TryParse(rule.data, out result))
                    return jobdescriptions;
                return jobdescriptions.Where(j => j.JobDescriptionID == Convert.ToInt32(rule.data));

            }

// Similar Statements

            return jobdescriptions;
        }



private IQueryable<JobDescription> orderJobDescription(IQueryable<JobDescription> jobdescriptions, string sortColumn, string sortOrder)
        {
            if (sortColumn == "JobDescriptionID")
                return (sortOrder == "desc") ? jobdescriptions.OrderByDescending(j => j.JobDescriptionID) : jobdescriptions.OrderBy(j => j.JobDescriptionID);

            return jobdescriptions;
        }

2 ответа

Решение

Исключение означает, что вам всегда нужен отсортированный ввод, если вы применяете Skipтакже в том случае, если пользователь не щелкает столбец для сортировки. Я мог бы представить, что столбец сортировки не указан, когда вы впервые открываете сетку, прежде чем пользователь сможет щелкнуть заголовок столбца. Чтобы поймать этот случай, я бы предложил определить некоторую сортировку по умолчанию, которую вы хотите, когда не указан другой критерий сортировки, например:

switch (sortColumn)
{
    case "JobDescriptionID":
        return (sortOrder == "desc")
            ? jobdescriptions.OrderByDescending(j => j.JobDescriptionID)
            : jobdescriptions.OrderBy(j => j.JobDescriptionID);

    case "JobDescriptionTitle":
        return (sortOrder == "desc")
            ? jobdescriptions.OrderByDescending(j => j.JobDescriptionTitle)
            : jobdescriptions.OrderBy(j => j.JobDescriptionTitle);

    // etc.

    default:
        return jobdescriptions.OrderBy(j => j.JobDescriptionID);
}

редактировать

О ваших последующих проблемах в соответствии с вашим комментарием: вы не можете использовать ToString() в запросе LINQ to Entities. И следующая проблема заключается в том, что вы не можете создать string массив в запросе. Я бы предложил загрузить данные из БД с их нативными типами, а затем преобразовать их в строки (и в массив строк) в памяти:

rows = (from j in jobdescription
        select new
        {
            JobDescriptionID = j.JobDescriptionID,
            JobTitle = j.JobTitle,
            JobTypeName = j.JobType.JobTypeName,
            JobPriorityName = j.JobPriority.JobPriorityName,
            Rate = j.JobType.Rate,
            CreationDate = j.CreationDate,
            JobDeadline = j.JobDeadline
        })
        .AsEnumerable() // DB query runs here, the rest is in memory
        .Select(a => new
        {
            id = a.JobDescriptionID,
            cell = new[] 
            { 
                a.JobDescriptionID.ToString(), 
                a.JobTitle,
                a.JobTypeName,
                a.JobPriorityName,
                a.Rate.ToString(),
                a.CreationDate.ToShortDateString(),
                a.JobDeadline.ToShortDateString()
            }
        })
        .ToArray()

У меня была такая же проблема после сортировки с использованием некоторого кода от Адама Андерсона, который принял общую строку сортировки в OrderBy.

Получив это исключение, я провел много исследований и нашел очень умное решение:

var query = SelectOrders(companyNo, sortExpression);

return Queryable.Skip(query, iStartRow).Take(iPageSize).ToList();

Надеюсь, это поможет!

SP

Другие вопросы по тегам