Расширенная функциональность универсального класса Grid в VFP.

Новости

1. Методы работы с удалёнными данными.
Основной задачей СУБД-приложения, основанного на модели «Клиент-Сервер», яв-ляется сохранение, удаление и редактирование данных, хранящихся на сервере (в данном случае имеется в виду SQL-сервер). Основным средством работы с данными является компонент класса Grid в Visual FoxPro.
Работа с объектом Grid может осуществляться в двух основных режимах:
— с использованием сквозных запросов,
— с использованием обновляемых курсоров.
Эти режимы значительно отличаются друг от друга, и имеют свои недостатки и пре-имущества. Рассмотрим подробнее режим использования обновляемых курсоров.
1.1. Использование обновляемых курсоров.

Под обновляемыми курсорами понимают высокоуровневые конструкции, которые служат для непосредственного доступа к данным SQL-сервера. Рассматриваемые объекты содержат информацию о способе соединения с сервером, спектре требуемых данных (строка запроса), буферизации и многое другое. Главным достоинством обновляемых кур-соров является существование встроенного механизма переноса изменённых данных на сервер (вставка, удаление, редактирование) или сброса изменённых данных (согласно бу-феризации), что снимает эту задачу с программиста. В обновляемых курсорах также пре-дусмотрен механизм импорта данных с сервера.
Но следует быть внимательным при ис-пользовании обновляемых курсоров в том случае, если:
— в таблицах SQL-сервера, входящих в состав запроса для обновляемого курсора, присутствуют поля типа Identity(автоинкрементный ключ);
— определены триггеры на таблицы SQL-сервера, присутствующие в запросе;
— объём запрашиваемых данных велик (более 50000 записей), т.к. временные затраты на импорт данных с сервера прямо пропорциональны объёму данных.
Преодолеть последний недостаток может помочь тот факт, что в Visual Fox Pro 8.0 появилась новая модель обновляемого курсора объект CursorAdapter, в котором, кроме всех преимуществ уже существовавшей модели (объекта RemoteView), появилась воз-можность изменять программно спектр запрашиваемых с сервера данных.
1.2. Использование сквозных запросов.
Режим использования сквозных запросов не имеет никаких ограничений в использо-вании и не требует больших временных затрат при импорте данных с сервера, но в данном случае на программиста ложится задача отслеживания изменённых данных и разработки механизма вставки, редактирования или удаления, а также задача обновления данных. В данном случае источником объекта Grid служит временная таблица (курсор), с которым производится вся работа.
2. Функциональность модифицированного класса Grid.
Был реализован модифицированный класс Grid, предоставляющий следующие до-полнительные функции:
— фильтрация данных объекта, рассчитанная на работу с источником объекта Grid (адаптером курсора, удалённым представлением, локальной таблицей);
— поиск данных;
— пакет функций (экспорт в Excel, предоставление списка различных значений ко-лонки, сумма по колонке и т.д.), вызываемых через меню по правой кнопке мыши;
— запрос данных с SQL-сервера с использованием объекта CursorAdapter, генерируе-мого программно.
Главное преимущество данного класса Grid состоит в его универсальности, т.е. все предоставляемые функции могут быть эффективно использованы в любом приложении, разработанном в среде Visual Fox Pro, если базовым классом для Grid является рассматри-ваемый модифицированный класс.
2.1. Фильтрация.
Эффективная организация фильтрации – один из важнейших аспектов при разработ-ке СУБД-приложения. Фильтрация записей – стандартная и распространенная операция, позволяющая пользователю выбирать нужные ему данные из всего объема данных. Пожа-луй, нет таких СУБД-приложений, в которых бы не использовались различные модули фильтрации. На программном уровне это происходит с помощью SQL запросов или фильтров. По сути дела фильтр – это запрос для одной таблицы.
Сейчас существует множество различных СУБД приложений, использующие свои средства построения запросов, и в каждом приложении существует свой собственный по-строитель фильтров (а в большинстве случаев и не один), ориентированный только под данную программу или экранную форму. В одних случаях это громоздкий модуль, в кото-ром нужно произвести большое количество операций, прежде чем добиться нужного ре-зультата, даже если нужно всего лишь произвести простой запрос к БД, в другом случае наоборот. Зачастую разработчики конструируют фильтр, позволяющий использовать только операцию равенства и ввод значений вручную, чего, на мой взгляд, недостаточно для более опытного пользователя.
Сравните два фильтра, показанных на рисунке 1 — уни-версальный(вверху) и неуниверсальный (внизу).

Рисунок 1. — Сравнение фильтров.

Также существуют множество конструкторов фильтров на английском языке, что может привести в тупик неквалифицированного пользователя.
Решено было разработать универсальное средство для конструирования фильтров, которое бы легко подключалось к СУБД приложению, имело полностью русифицирован-ный интерфейс, в том числе и для логических операций, могло бы предоставлять пользо-вателю выбор между созданием простого или сложного запроса. Причем, если необходи-мо создать простой фильтр, то и интерфейс программы должен быть простым, а если сложный фильтр, то и интерфейс и средства для его создания должны быть достаточными. Таким образом, при использовании данного модуля, разработчику не нужно создавать для каждой экранной формы свой фильтр, а пользователю – разбираться с интерфейсом боль-шого количества фильтров, так как во всем приложении он будет единым.
В форме фильтра пользователю необходимо выбрать поле, на которое налагается от-ношение, само отношение и значение (см. рисунок 2).

Рисунок 2. — Форма построения простого фильтра

Для построения нового условия необходимо выбрать поле, на которое налагается ус-ловие, предполагаемый тип условия (>,<,= и многое другое) значение того же типа дан-ных, что и выбранное поле (см. Рисунок 3). Рисунок 3. — Выбор параметров для генерации условия. В данном модуле предусмотрено несколько вариантов определения значения, вхо-дящего в условие:
— непосредственный ввод значения с клавиатуры в TextBox,
— выбор из списка присутствующих значений данного поля путём нажатия на кноп-ку «…» расположенную рядом с TextBox.
После нажатия на кнопку «…» на экране появляется форма, содержащая значения данного поля (Рис.4) , после выбора одного из них необходимо нажать кнопочку «ОК» или произвести двойной щелчок мыши на месте выбранного значения.
Дополнительной возможностью в модуле является просмотр списка различных зна-чений выбранного столбца.

Рис 4. Форма просмотра различных значений.

В фильтре существует возможность использования отрицания, отмены фильтра, а также вызова формы сложного фильтра.
Для того чтобы воспользоваться фильтром для какой-либо таблицы необходимо до-бавить в соответствующую форму вызов фильтра (например, в метод init). Всю необходи-мую информацию (имя источника данных, название столбцов, текущее поле фильтрации, а также чаще всего применяемую логическую операцию для заданного поля) модуль ав-томатически возьмет из соответствующих свойств экранной формы и расположенной на ней таблицы.
Но не всегда одного условия в выражении фильтрации достаточно для отбора нуж-ной информации. Это часто случается, когда фильтруемая таблица содержит множество полей и фильтр по одному из них не будет достаточен. На этот случай в модуле фильтра-ции предусмотрен раздел «Сложный фильтр» (см Рисунок 5).

Рисунок 5. — Форма построения сложного фильтра

Форма сложного фильтра предусматривает возможность составления условий, где значениями могут служить как другие однотипные поля источника объекта Grid, так и формулы, включающие однотипные поля.
Замечу, что все условия фильтрации генерируются на русском языке, что облегчает понимание неопытному пользователю. Также присутствует возможность сохранения и редактирования сложных фильтров для последующего использования определённым пользователем с определённой таблицей. Хранение сложных фильтров может произво-диться, как на сервере (если есть доступ к удалённым данным), так и на локальной маши-не (в случае отсутствия доступа к серверу). Репозиторий фильтров создаётся автоматиче-ски, если таковой отсутствует.
2.2. Поиск данных.
В состав модуля фильтрации включены средства поиска данных. При осуществле-нии поиска (например, через контекстное меню или горячую клавишу) появляется набор различных значений исходного столбца (см. Рисунок 4), из которого можно выбрать инте-ресующее или указать своё значение. Результатом является положение первого вхождения указанного значения в данном столбце. Также существует возможность поиска дальней-ших вхождений данного значения по средствам горячей клавиши или контекстного меню. При выборе определённого значения из списка, для облегчения идентификации интере-сующего значения, возможно использование поиска по вхождению строки указанной в поле ввода.
2.3. Работа с обновляемыми курсорами.
Обновляемые курсоры можно создавать, как программно, так и с использованием конструктора. Имеющиеся конструкторы для обновляемых курсоров в некоторых случаях работают некорректно.
При осуществлении работы с обновляемыми курсорами выявились следующие про-блемы:
— возникла потребность в автоматизации процесса создания и изменения обновляе-мого курсора, поскольку такие операции производятся достаточно часто;
— изменение структуры БД приводит к необходимости каждый раз пересоздавать обновляемый курсоры;
— неавтоматизированный переход от объекта RemoteView к CursorAdapter и обратно является трудоёмким;
— некорректная работа конструктора объекта CursorAdapter в случае таблиц с боль-шим количеством полей.
Была разработана собственная модель формирования RemoteView, которая включает в себя две программы. Одна из программ служит для создания по xml-спецификации уда-ленного представления в СУБД-приложении, другая же предназначена для обратного дей-ствия – по существующему Remote View создать спецификацию в виде xml-файла. Xml-спецификации могут храниться как в одном файле, так и в разных файлах.
Модель создания адаптера курсора формирует CursorAdapter, который является точ-ной копией RemoteView в соответствии со строкой запроса, способом соединения, спи-ском автоматически обновляемых полей и помещает обновляемый курсор в DataInvironment экранной формы, удаляя при этом исходный RemoteView.
Обновление курсора осуществляется независимо от типа. Для RemoteView происхо-дит просто перезагрузка данных с SQL-сервера с сохранением текущей записи курсора. Для CursorAdapter происходит загрузка информации с SQL-сервера с использованием но-вого условия, полученного путём использования модуля фильтрации.

Рисунок 6. — Форма для выбора параметров условия строки запроса

Интерфейс построения условия фильтрации аналогичен интерфейсу построения ус-ловия строки запроса (см. Рисуноки 2 и 6).
В рассматриваемой форме существует возможность импорта всех строк обновляемо-го курсора (без указания спектра данных) или интересующих строк обновляемого курсо-ра (формирование и использование условия строки запроса).
Предусмотрено несколько вариантов определения значения, входящего в условие запроса:
— указание значения с клавиатуры в TextBox,
— выбор из списка представленных в объекте CursorAdapter значений данного поля (кнопка «…» рядом с TextBox),
— выбор из списка различных значений данного поля, хранящихся на сервере, в форме (см. Рис. 4) путём нажатия на кнопку «….».
Изменение строки запроса программно основано на том, что исходная строка разби-вается на смысловые части такие, как:
— список запрашиваемых полей, связей между таблицами(часть оператора SELECT до WHERE);
— постоянная часть условия запроса – это та часть, которая присутствовала при соз-дании обновляемого курсора;
— переменная часть условия запроса;
— список полей сортировки.
Изменение спектра запрашиваемых данных происходит путём формирования усло-вия в экранной форме (см. Рисунок 6) и добавления этого условия к переменной части ус-ловия строки запроса.
При создании объекта CursorAdapter в общем случае переменная часть условия не содержит отношений, но существует возможность определения переменной части условия запроса при инстанцировании обновляемого курсора, передавая значение в качестве пара-метра в процедуру создания адаптера курсора.
3. Заключение.
Разработчику СУБД-приложения приходиться создавать множество фильтров для экранных форм. Эти модули выполняют одинаковые операции, но используются для раз-ных таблиц и различных экранных форм, что не позволяет использовать один и тот же фильтр. Это вынуждает разработчика постоянно переписывать код фильтра.
Для решения этой проблемы был написан модуль фильтрации, отличительными свой-ствами которого является:
— удобный пользовательский интерфейс;
— простая технология подключения фильтра;
— универсальность;
— полностью русифицированный интерфейс;
— выбор между созданием простого запроса или сложного;
— возможность построения условий для объектов Cursor Adapter;
— возможность пополнения условий фильтрации за счёт точек вставки.
В ходе работы был практически создан новый, расширенный класс объекта Grid с од-ним дополнительным методом – методом фильтрации данных. Параметры метода полно-стью определяется источником данных объекта Grid, и разработчику нет необходимости писать собственные программы фильтрации.
Кроме того, была решена проблема модификации удаленных представлений, возни-кающая при изменении структуры базы данных. Как правило, разработчику приходится проделывать эту операцию вручную.
Для автоматизации этой операции были написаны программы, которые позволяют автоматически создавать и обновлять удаленные представления. Для этого информация о Remote View хранится в так называемой спецификации удаленных представлений, по ко-торой в случае необходимости можно создать само представление. Достоинствами данно-го механизма является:
— централизованное хранение информации об удаленных представлениях;
— наглядность и простота изменения этой информации;
— расширенный синтаксис записи SQL-выражения;
— для создания спецификации необходимо минимум информации о представлении.
Также был реализован модуль динамической генерации объекта CursorAdapter по указанному RemoteView. Это позволило избежать трудностей, возникающих при созда-нии объекта CursorAdapter с помощью конструктора:
— некорректная работа конструктора в некоторых ситуациях;
— влияние человеческого фактора, т.е. возникновение ошибок, непреднамеренно вно-симых разработчиком в процессе создания.
Применение описанных технологий позволило:
— значительно сократить вероятность возникновения различного рода ошибок, в том числе и ошибок конструкторов обновляемых курсоров;
— уменьшить объём вносимой информации при формировании обновляемого курсо-ра;
— автоматизировать процесс создания объекта CursorAdapter по RemoteView и об-новляемых курсоров в целом;
— разработать собственную модель создания обновляемого курсора;
— избежать повторного создания обновляемых курсоров при изменении структур таблиц базы данных.
Это позволило существенно оптимизировать загрузку данных с SQL-сервера, а, сле-довательно, повысить эффективность работы приложений.