Существует два типа фильтров:
- SyncFilter - позволяет ограничить передаваемые пользователю данные. В результате работы фильтра, в базе данных пользователя будут только те данные, которые ему необходимы, и к которым он имеет доступ.Это крайне актуально для мобильных приложений, работающих на не самом быстром оборудовании и при низкой пропускной способности сети.
- DeleteFilter - позволяет удалять данные из базы данных мобильного приложения, которые уже не являются актуальными. Все данные, попадающие под фильтр будут удалены из таблицы на мобильном устройстве после синхронизации с сервером.
Фильтры являются частью объектной модели решения (файла метаданных).
Синтаксис
Значение фильтра необходимо присвоить атрибуту SyncFilter(DeleteFilter) объекта, на который он накладывается, и(или) его табличной части(частей). Если фильтр задан для табличной части и основного объекта - сервер применит оба.
Фильтр представляет собой SQL выражение, следующее после условия WHERE.
При формировании фильтра DeleteFilter необходимо обрамлять имя схемы таблицы нижними подчеркиваниями (например _Catalog_Entity вместо Catalog.Entity)
Фильтр выполнятся в контексте, в котором:
- псевдоним "Т" ссылается на таблицу, к которой применяется условие
- переменная @UserId содержит идентификатор текущего пользователя.
Например:
T.SR = @UserId AND T.PlanStartDataTime > (GETDATE() - 10) // записи текущего пользователя с датой не старше 10 дней
_Catalog_Accounts.Description='12345'//записи со значением '12345' в поле Description
In-фильтры в атрибуте SyncFilter
В случае необходимости использования вложенных запросов следует использовать оператор IN.
Сервер GROTEM допускает только один "внешний" оператор IN в выражении, например:
T.Owner IN (SELECT Id FROM Catalog.SKUGroup WHERE Manager = @UserId)
Выражения вида T.Owner IN (SELECT Id FROM Catalog.SKUGroup WHERE Manager = @UserId) AND T.PlanStartDataTime > (GETDATE() - 10) недопустимы. Всю сложную логику следует помещать в скобках - там ограничений нет, например:
T.Id IN (SELECT Id FROM Catalog.SKU WHERE Owner IN (SELECT Id FROM Catalog.SKUGroup WHERE Manager = @UserId) AND T.PlanStartDataTime > (GETDATE() - 10))
Выражение IN допустимо только по отношению к полю ссылочного типа.
Принцип работы
Простые (не IN-фильтры) применяются при синхронизации мобильного агента в момент определения сервером, какие записи следует возвратить. При этом если синхронизация не первая, и выборка изменилась с момента последней синхронизации (например условие фильтра включает в себя текущую дату) - "старые" записи останутся в базе данных устройства, хотя формально под условие фильтра они уже не попадают.
Для решения данной проблемы, и более сложных случаев, когда, например, выборка зависит от набора записей в других таблицах (нужно вернуть торговые точки добавленные в территории текущего торгового представителя), следует использовать In-фильтры, которые сервер GROTEM отрабатывает по более сложному сценарию:
- Для каждого объекта с In-фильтром при выгрузке метаданных сервер создает таблицу ИмяОбъекта_filterids
- В начале сеанса синхронизации мобильного агента сервер вычисляет выражение фильтра и помещает идентификаторы в таблицу filterids:
Идентификаторы, отсутствующие в таблице, помечаются как "новые".
Идентификаторы, присутствующие в таблице, но отсутствующие в выборке, помечаются как "удаленные".
- Используя статусы записей, сервер возвращает мобильному агенту новые записи и информацию о том, какие записи следует удалить.
- Таблицы filterids очищаются при первичной синхронизации мобильного агента (и очистке кеша).
Рекомендации
- Не рекомендуется использовать псевдонимы таблиц, оканчивающиеся на Т
- Названия полей желательно обертывать в квадратные скобки [], чтобы избегать конфликтов с ключевыми словами MS SQL Server (например T.[User] вместо T.User)
- При использовании In-фильтров следует помнить, что сервер хранит идентификаторы объектов в таблицах filterids для каждого пользователя. Поэтому следует быть "аккуратнее в выражениях", желательно чтобы фильтр возвращал минимум записей. Например:
Если необходимо отфильтровать справочник товаров (Catalog.SKU) по группе номенклатуры (Catalog.SKUGroup), можно использовать выражения:
T.Id IN (SELECT Id FROM Catalog.SKU S JOIN Catalog.SKUGroup SG ON S.Owner = SG.Id WHERE SG.Manager = @UserId)
T.Owner IN (SELECT Id FROM Catalog.SKUGroup WHERE SG.Manager = @UserId)
В первом варианте в таблицу filterids будут помещены идентификаторы товаров, которых может быть на порядки больше чем идентификаторов групп второго выражения. Что приведет к дополнительной нагрузке на сервер.
Добавить комментарий