Как обрабатывать запросы к удаленным данным и данным кэша

Ищете хороший способ одновременного запроса удаленных данных и локального кеша. Мне нужно иметь возможность запрашивать удаленные данные, но объединять результаты с локальными изменениями.

Поэтому, если я добавлю элемент «Боб» и получу первые 5 результатов в алфавитном порядке по возрастанию, вместо «Аарон, Адам, Алиса, Эшли, Бад» я получу «Аарон, Адам, Алиса, Эшли, Боб» и если бы я запросил вторые 5 результатов (пропустить 5, взять 5), список начинался бы с «Bud». Это также должно обрабатывать удаление, поэтому, если я локально удалил элементы 1 и 3 и запрашиваю первые 50 элементов, я хочу получить элементы со 2 и 4 по 52. И, наконец, запросы для фильтрации должны быть адресованы как серверу, так и изменения в локальном кэше: поэтому, если я изменю имя «Сэм» на «Боб» и запросю все имена, начинающиеся с буквы «Б», я должен получить новую запись Сэма о Бобе с Биллом и парнями.

Обычно мы просто загружаем все строки с начальным запросом и позволяем queryLocally обрабатывать работу, но есть проблема, потому что мы работаем с 10 000 записей или более.

Любая помощь приветствуется!


person Jonneh    schedule 05.12.2012    source источник
comment
Откровенно говоря, это очень сложная задача... намного сложнее, чем кажется на первый взгляд. Мы решили эту проблему в DevForce с помощью EntityQueryPager. Если вам (и другим) нужна эта функция, проголосовать за него в User Voice.   -  person Ward    schedule 12.12.2012
comment
Уорд, мой голос принят. Спасибо за ответ. Это именно то решение, которое нам нужно.   -  person Jonneh    schedule 12.12.2012
comment
Я не хочу возлагать на тебя слишком большие надежды. Я рад, что вы голосуете за него. Если он наберет достаточно голосов, мы поднимем его в очередь. Мы будем рады предоставить исходный код компонента DF, если кто-то захочет создать версию JS до того, как мы доберемся до нее. Дайте нам знать.   -  person Ward    schedule 13.12.2012


Ответы (3)


Одним из возможных решений для вашего сценария было бы запросить у сервера «немного больше», чем ожидалось в результате, но в конечном итоге всегда фильтровать локальный кеш. Сделайте локальный кеш единственным источником и фильтруйте/берите/пропускайте из него.

Теперь попробуем определить, что значит «еще немного».

если я изменю имя «Сэм» на «Боб» и запросю все имена, начинающиеся с «Б», я должен получить новую запись Сэма о Бобе с Биллом и парнями.

Это должно работать так, как вы ожидаете - не нужно получать с сервера больше, чем «имена, начинающиеся с B».

если я добавлю элемент «Боб» и получу первые 5 результатов в алфавитном порядке по возрастанию, вместо «Аарон, Адам, Алиса, Эшли, Бад» я получу «Аарон, Адам, Алиса, Эшли, Боб» и если бы я запросил вторые 5 результатов (пропустить 5, взять 5), список начинался бы с «Bud».

Чтобы это работало, вам нужно получить удаленно, например: взять numberOfEntitiesChangedLocally + ( pageNr * recordsPerPage ), а затем пропустить и взять из локального кеша обычным способом.

person pawel    schedule 06.12.2012
comment
Павел, Спасибо за ответ. Я тестировал эти сценарии с помощью примера, доступного в NuGet, и обнаружил, что некоторые из ваших предположений не соответствуют действительности. Например: если у меня есть 4 элемента и 1 в контрольном списке установлен как IsDone, и я запрашиваю IsDone == true, я получу 1 результат. Если я локально изменю второй элемент на IsDone, запрос все равно даст мне только 1 результат; что создает проблему с определением того, что ДОЛЖНО быть включено в запрос из локального кеша. Это более серьезная проблема, чем обратная ситуация (которая тоже случается), когда запрос на IsDone == false возвращает 3. - person Jonneh; 06.12.2012
comment
Результат запроса к серверу будет содержать только одну сущность - это нормально. Когда этот объект извлекается (в локальный кеш), вы должны получить два объекта из локального запроса. Вы должны выполнить два запроса - первый удаленный запрос (игнорировать результаты), следующий локальный запрос, который должен вернуть то, что вы ожидаете. - person pawel; 06.12.2012
comment
Проблема, с которой я столкнулся с этим решением, заключается в том, что если я возьму страницу 1, а затем перейду на страницу 3, локальный кеш будет думать, что есть только 2 страницы данных вместо 3. Я бы предпочел не запрашивать страницы 1. на (n - 1), чтобы правильно запрашивать предварительные записи локального кэша. - person Jonneh; 06.12.2012
comment
Я понимаю, что вы имеете ввиду. Когда пользователь выбирает просмотр последней из 1000 страниц, нам нужно получить все (возможно, 20000) записей - чего вы хотите избежать. Попробуйте переосмыслить бизнес-правила конкретного приложения, которое вы пишете. Может быть, вы найдете лучший алгоритм для пейджинга? Или, может быть, вы можете согласиться на выборку абсолютного минимума данных, представляющих информацию, необходимую для пейджинга? Например, вы можете получить идентификатор и field_used_for_orderBy всех записей, а затем использовать эту информацию на клиенте для вычисления (включая ожидающие локальные изменения), какие идентификаторы принадлежат странице n. - person pawel; 07.12.2012

Три примера комбинированных удаленных и локальных запросов находятся в файле \Samples\DocCode. Возможно, они помогут.

Здесь добавлены комментарии. Полный код находится в queryTests.js

1. * Объедините удаленный и локальный запросы, чтобы получить всех клиентов * включая новых, несохраненных клиентов * v1 - Использование FetchStrategy

2. * Объедините удаленный и локальный запросы, чтобы получить всех клиентов * включая новых, несохраненных клиентов * v1 = использование FetchStrategy.FromLocalCache

3. * Объедините удаленный и локальный запросы, чтобы получить всех клиентов * включая новых, несохраненных клиентов * v2 = использование ExecuteLocally()

Вас также может заинтересовать интересный пример того, как этого больше не делать (также в queryTests:

    /*********************************************************************
    * This portion of the "queryTests (by id)" module  
    * tests a hand-built async getById utility that was the way to do it 
    * before EntityManager.fetchEntityByKey
    * A curiosity now.
    ********************************************************************/

    // This hand-built async getById utility method returns a promise.
    // A successful promise returns the entity if found in cache 
    // or if found remotely.
    // Returns null if not found or if found in cache but is marked deleted.
    // Caller should check for query failure.
    // 'queryResult' reports if queried the remote service 
    // and holds a found entity even if it is marked for deletion.
    // 
    // This fnc has been replaced by EntityManager.getEntityByKey.
person John    schedule 06.12.2012
comment
Это примеры объединения Remote и Local, но они получают весь набор с сервера. В этом случае Джонне не может получить весь набор, поэтому примеры неприменимы и не решат его проблему. - person Ward; 07.12.2012

Это должно быть достижимо в java-скрипте, серебряный свет может сделать то, что кому-то может понадобиться, чтобы увидеть, как это делается, это серебряный свет и портировать его на java-скрипт.

Я думаю, что логика должна быть такой, когда переключатель установлен (AlwaysRefreshDataOnQuery = false), а затем пропускается, перезаписывая измененные строки (включая удаления), в противном случае просто очистите локальный кеш и обновите его новыми данными.

Silver Light была очень мощной платформой, на сегодняшний день я не видел такой мощной платформы, как Silver Light (по крайней мере, в мире .NET).

person NSS    schedule 09.12.2012