2015-06-03 3 views
3

Я реализовал пользовательский IQueryable, который открывается через конечную точку OAPA WebAPI. Структура Get контроллера() является довольно стандартным:

[EnableQuery(
    AllowedQueryOptions = AllowedQueryOptions.Count 
          | AllowedQueryOptions.Filter 
          | AllowedQueryOptions.OrderBy 
          | AllowedQueryOptions.Skip 
          | AllowedQueryOptions.Top)] 
[ODataRoute] 
public PageResult<Foo> Get(ODataQueryOptions<Foo> queryOptions) 
{ 

    var bars = new QueryableData<Foo>(_provider); 

    var result = ((IQueryable<Foo>)queryOptions 
     .ApplyTo(bars, 
      new ODataQuerySettings(new ODataQuerySettings { EnableConstantParameterization = false, EnsureStableOrdering = false }))).ToList(); 
    var count = _provider.Count; 
    return new PageResult<Foo>(result, null, count); 
} 

странное поведение я вижу, является то, что OData $ Скип в строке запроса применяется после того, как PageResult возвращается. Например:

  • если строка запроса содержит $ топ = 10 & $ пропустить = 10 будет не возвращать никаких результатов.
  • если строка запроса содержит? & top = 12 & skip = 10 будет (2) возвращены результаты.

То, что я хочу сделать, - это предотвратить использование рамок (ы) для перехода к моим результатам, поскольку поставщик запросов уже реализует пропуск. Есть ли ODataQuerySettings, которые можно установить для предотвращения этого двойного применения пропусков?

EDIT: При дальнейших исследованиях, когда я удаляю $ count = true из строки запроса, пропустите (и верхнюю) функцию, как ожидалось. Это заставляет меня поверить, что мой подход к реализации $ count = true неверен. Из моих сеансов отладки кажется, что когда $ count = true в параметрах запроса, в запросе есть дерево выражений, примененное к нему дважды, один раз с возвращаемым типом long, а затем снова без выражения countlong wrapping. Я попытался вернуть счет на первый проход, а затем правильно запросить второй проход, но это приводит к отложенному применению выражения пропуска. Кажется, есть что-то очень фундаментальное, что мне здесь не хватает.

ответ

3

Прочитав список проблем Github, я наткнулся на это сообщение: OData PageResult method ignoring count parameter when using EnableQuery attribute #159. Кажется, что проблема заключается в сочетании атрибута EnableQuery и параметризованного Get-конструктора с использованием ODataQueryOptions. Используя оба способа, чтобы реализовать варианты запросов конструктора, применяя выражения запроса, тогда фреймворк будет применять те фильтры, которые он может по направлению от применяемого атрибута; поэтому двойное применение таких вещей, как skip, top и orderby.

+0

Awesome. Спасибо за это. – DarrellNorton

2

Поскольку я хотел сам справиться с этим пропуском, но мне все еще нужны другие функции EnableQueryAttribute, которые я видел, и заметил, что он виртуальный. Я создал производный класс, а затем попытался переопределить методы ApplyQuery. К сожалению, у ODataQueryOptions были только частные наборы по своим свойствам, поэтому я немного исказил их. (Он чувствует себя грязным, но эй ..)

public override IQueryable ApplyQuery(IQueryable queryable, ODataQueryOptions queryOptions) 
{ 
    var skipOption = new SkipQueryOption("0", queryOptions.Context); 
    typeof(ODataQueryOptions).GetProperty("Skip").SetValue(queryOptions, skipOption, null); 

    return base.ApplyQuery(queryable, queryOptions); 
} 

С вариантом пропуска в настоящее время 0 не применять его при построении ответа и не больше «двойного блюза пропуска».

Смежные вопросы