Entity Framework 4 - простое внутреннее исключение Compiled Query при компиляции

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

internal static readonly Func<MyEntities, string, int, int, IQueryable<Model.Message>> MessagesPagedSortedByDateQuery =
        CompiledQuery.Compile((MyEntities db, string folderId, int pageSize, int pageIndex) =>
        (
            db.Messages.Where(m => m.FolderId == folderId).OrderBy(m => m.Date).Skip(pageSize * pageIndex).Take(pageSize)
        ));

Это кажется мне очень простым запросом. Однако, когда я выполняю это со следующим утверждением:

var messages = MessageCompiledQueries.MessagesPagedSortedByDateQuery(myEntities, folderId, pageSize, pageIndex).ToList();

Я получаю следующее исключение из источника System.Data.Entity:

Число должно быть выражением DbConstantExpression или DbParameterReferenceExpression. Имя параметра: количество

С помощью этой трассировки стека:

в System.Data.Common.CommandTrees.ExpressionBuilder.Internal.ArgumentValidation.ValidateSkip(входные данные DbExpressionBinding, IEnumerable'1 sortOrder, DbExpression count) в System.Data.Common.CommandTrees.ExpressionBuilder.Db, DbExpression count) в System.Data.Objects.ELinq.ExpressionConverter.OrderByLifter.ApplySortOrderToSkip(входное выражение DbExpression, DbSortExpression, DbExpression k) в System.Data.Objects.ELinq..Data.Objects.ELinq.ExpressionConverter.Skip(входные данные DbExpressionBinding, DbExpression skipCount) в System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SkipTranslator.TranslatePagingOperator(оператор DressionExject.ELinq.ExpressionConverter.MethodCallTranslator.PagingTranslator.TranslateUnary(Родитель ExpressionConverter, операнд DbExpression, MethodCall Выражение выражения) в System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.UnarySequenceMethodTranslator.Translate(вызов ExpressionConverter, вызов метода MethodCallExpression) в System.Data.Objects.ELinq.ExpressionConverression.Player.Exchange.Exchange.Exchange.Exchange.Exchange.Exchange. sequenceMethod) в System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate (родитель ExpressionConverter, MethodCallExpression linq) в System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator'1.Translate, выражение Expression в выражении (выражение).Objects.ELinq.ExpressionConverter.TranslateExpression (Выражение linq) в System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.UnarySequenceMethodTranslator.Translate(выражение ExpressionConverter, вызов метода CallExpression.TellTellTerans_Exject_Conject_Exject_Conject_Conject_Conject_Conject_Conject_Conject_Conject_Conject_Conject_Conject_Conject_Conject_Conject_Conject_Conject_Conject_Conject_Conject_Conject_Conject_Conject_Exservice.Ru.RT.R.dll_RT.R.dll Перевести (Expressio Родитель nConverter, вызов MethodCallExpression, SequenceMethod sequenceMethod) в System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) в System.Data.Objects.ELinq.Transinter.Express Выражение linq) в System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Выражение linq) в System.Data.Objects.ELinq.ExpressionConverter.Convert() в System.Data.Objects.ELinq.CompiledELinqQueryState.GetExecutionPlanOble_lang forNul) в System.Data.Objects.ObjectQuery'1.GetResults (Nullable'1 forMergeOption) в System.Data.Objects.ObjectQuery'1.System.Collections.Generic.IEnumerable.GetEnumerator() в System.Collections.Generic.List'1..ctor(коллекция IEnumerable'1) в System.Linq.Enumerable.ToList[TSource](источник IEnumerable'1) в MyApp.Data.Repository.MessageRepository.GetByFolder(String folderId, Int32 pageSize, Int32 pageIndex, String sortField) в C:\Projects\MyApp\MyApp.Data\Repository\MessageRepository.cs: строка 40 в MyApp.WebClient.Controllers.FolderController.Messages(команда GridCommand, String folderId) в C:\Projects\MyApp\MyApp.WebClient\Controllers\FolderController.cs: строка 53 в lambda_method(Closure, ControllerBase, Object[]) в System.Web.Mvc.ActionMethodDispatcher.Execute(контроллер ControllerBase, параметры Object []) в System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, параметры IDictionary`2) в System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, параметры ActionDescriptor, ActionDescriptor, IDictionary'2) в System.Web.Mvc.ControllerActionInvoker.<. Cd.__.Mvc.ControllerActionInvoker.InvokeActionMethodFilter (фильтр IActionFilter, предварительный контекст ActionExecutingContext, продолжение Func'1)

Похоже, что исключение возникает при компиляции запроса в первый раз. Если я удаляю orderby из запроса, он работает просто отлично. Но, очевидно, я бы хотел, чтобы упорядочение и подкачка страниц происходили на сервере, поэтому я не хочу делать это после получения полной таблицы. Это ошибка в структуре сущностей? Я не могу найти ничего об этом в Интернете. Кто-нибудь знает, как обойти это? Я использую окончательный выпуск.Net Framework 4 с Visual Studio 2010.

Спасибо!

1 ответ

Решение

Посмотрим, исправит ли это:

internal static readonly Func<MyEntities, string, int, int, int, IQueryable<Model.Message>> 
    MessagesPagedSortedByDateQuery =
        CompiledQuery.Compile((MyEntities db, string folderId, int pageSize, int pageIndex, int skipCount) =>
        (
            db.Messages.Where(m => m.FolderId == folderId).OrderBy(m => m.Date).Skip(skipCount).Take(pageSize)
        ));

Обратите внимание, что я изменил подпись. Это, очевидно, не идеальное решение, но я не видел, как вы используете это в контексте кода. Если это поможет вам избежать ошибки, вы можете настроить ее на что-то более полезное.

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