При работе с базой данных в многопользовательской среде, важно отобразить пользователю только те данные, которые ему необходимы, и к которым он имеет доступ.

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

В платформе Grotem данная проблема решается с помощью фильтров синхронизации, являющихся частью объектной модели решения (файла метаданных).

Синтаксис

Значение фильтра необходимо присвоить атрибуту SyncFilter объекта, на который он накладывается, и(или) его табличной части(частей). Если фильтр задан для табличной части и основного объекта - сервер применит оба. 

Фильтр представляет собой SQL выражение, следующее после условия WHERE.

Фильтр выполнятся в контексте, в котором:

  • псевдоним "Т" ссылается на таблицу, к которой применяется условие
  • переменная @UserId содержит идентификатор текущего пользователя.

Например: T.SR = @UserId AND T.PlanStartDataTime > (GETDATE() - 10) (записи текущего пользователя с датой не старше 10 дней)

In-фильтры

В случае необходимости использования вложенных запросов следует использовать оператор 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 будут помещены идентификаторы товаров, которых может быть на порядки больше чем идентификаторов групп второго выражения. Что приведет к дополнительной нагрузке на сервер.

Внесение изменений в выражения фильтров

Для изменения фильтров без перевыгрузки метаданных и пересоздания базы с нуля, следует использовать команду -dmf утилиты utils.exe. 


  • Нет меток
Написать комментарий...