Дуг Хенниг
Класс CursorAdapter — одна из самых важных новых функций в VFP 8, поскольку он обеспечивает простой в использовании и согласованный интерфейс для удаленных данных. В статье этого месяца Дуг исследует CursorAdapters и то, как они работают. В следующем месяце мы рассмотрим некоторые дополнительные способы их использования.
- Удаленные представления, основанные на соединениях ODBC.
- Функции транзита SQL (SPT), такие как SQLCONNECT(), SQLEXEC() и SQLDISCONNECT(), которые также основаны на соединениях ODBC.
- Объекты данных ActiveX или ADO, которые предоставляют объектно-ориентированный интерфейс для поставщиков OLE DB для механизмов баз данных.
- XML, который представляет собой облегченный, независимый от платформы механизм передачи данных.
- Это упрощает использование ODBC, ADO или XML, даже если вы не очень хорошо знакомы с этими технологиями.
- Он обеспечивает согласованный интерфейс для удаленных данных независимо от выбранного вами механизма.
- Это позволяет легко переключаться с одного механизма на другой.
Вот пример (CursorAdapterExample.prg, включенный в загружаемые материалы для подписчиков этого месяца), который извлекает определенные поля для бразильских клиентов из таблицы Customers в базе данных Northwind, поставляемой с SQL Server. Курсор можно обновлять, поэтому, если вы внесете изменения в курсор, закроете его, а затем снова запустите программу, вы увидите, что ваши изменения были сохранены в бэкэнде.
DataEnvironment и изменения формыlocal lcConnString, ; loCursor as CursorAdapter, ; laErrors[1] lcConnString = 'driver=SQL Server;server=(local);' + ; 'database=Northwind;uid=sa;pwd=;trusted_connection=no' * change password to appropriate value for your database loCursor = createobject('CursorAdapter') with loCursor .Alias = 'Customers' .DataSourceType = 'ODBC' .DataSource = sqlstringconnect(lcConnString) .SelectCmd = "select CUSTOMERID, " + ; "COMPANYNAME, CONTACTNAME from CUSTOMERS " + ; "where COUNTRY = 'Brazil'" .KeyFieldList = 'CUSTOMERID' .Tables = 'CUSTOMERS' .UpdatableFieldList = 'CUSTOMERID, COMPANYNAME, ' + ; 'CONTACTNAME' .UpdateNameList = ; 'CUSTOMERID CUSTOMERS.CUSTOMERID, ' + ; 'COMPANYNAME CUSTOMERS.COMPANYNAME, ' + ; 'CONTACTNAME CUSTOMERS.CONTACTNAME' if .CursorFill() browse else aerror(laErrors) messagebox(laErrors[2]) endif .CursorFill() endwith
Для поддержки нового класса CursorAdapter в классы DataEnvironment и Form и их конструкторы внесено несколько изменений.
Во-первых, как я упоминал ранее, класс DataEnvironment теперь имеет свойства DataSource и DataSourceType. Он не использует эти свойства сам по себе, но они используются любым членом CursorAdapter, для которого UseDEDataSource установлено в .T. Во-вторых, теперь вы можете визуально создавать подклассы DataEnvironment с помощью конструктора классов (ух ты!).
Что касается форм, теперь вы можете указать подкласс DataEnvironment для использования, установив новые свойства DEClass и DEClassLibrary. Если вы сделаете это, все, что вы сделали с существующей средой DataEnvironment (курсоры, код и т. д.), будет потеряно, но, по крайней мере, вас сначала предупредят. Интересная новая функция форм, которая в чем-то связана, — это свойство BindControls; установив это на .F. в окне свойств означает, что VFP не будет пытаться привязать данные к элементам управления во время инициализации, только если вы установите для BindControls значение .T. Для чего это нужно? Ну, сколько раз вы проклинали, что параметры передаются в Init, который срабатывает после того, как все элементы управления были инициализированы и привязаны к своим источникам управления? Что делать, если вы хотите передать параметр в форму, которая сообщает ей, какую таблицу открывать, или другие вещи, влияющие на ControlSource? Это новое свойство делает эту проблему проще простого.
Преимущества
Есть много веских причин использовать CursorAdapters вместо удаленных представлений, SPT, ADO или XML.
- Каждый механизм имеет свой интерфейс. С удаленными представлениями вы открываете их с помощью команды USE. В SPT вы используете SQLCONNECT() и SQLEXEC() для создания курсора. С помощью ADO вы создаете объекты ADO Connection и RecordSet (и, возможно, объект Command, в зависимости от того, как вы извлекаете данные) и вызываете их методы Open. При использовании XML вы сначала откуда-то получаете строку XML (например, из компонента COM в многоуровневом приложении или из SQL Server через SQLXML), а затем используете XMLTOCURSOR() для преобразования ее в курсор VFP. Запись обновлений на серверную часть также отличается для каждого механизма. Таким образом, при переходе от одного механизма к другому у вас появляются новые методы для изучения, плюс вам, возможно, придется переписать большую часть существующего кода.
CursorAdapter’ы имеют согласованный интерфейс независимо от того, какой механизм вы используете для извлечения данных. Вы устанавливаете различные свойства объекта и вызываете метод CursorFill для извлечения данных, работаете с курсором, как с любым другим курсором VFP, а затем вызываете TABLEUPDATE() (или позволяете VFP обрабатывать его автоматически), чтобы записать изменения обратно.
- В среде разработки часто требуется открыть курсор из командного окна, чтобы просмотреть его содержимое. Это легко для удаленных представлений (просто USE представление), но гораздо больше работы для SPT, ADO и XML.
В зависимости от того, как он настроен (например, если он полностью автономен), открытие курсора из подкласса CursorAdapter может быть почти таким же простым, как открытие удаленного представления: вы просто создаете экземпляр подкласса и вызываете метод CursorFill. Вы даже можете вызвать это из Init, чтобы сделать это одноэтапной операцией.
- Увеличение существующего приложения может быть относительно простым с удаленными представлениями: вы заменяете существующие объекты Cursor, которые указывают на локальные таблицы или представления в DataEnvironment, на те, которые вместо этого ссылаются на удаленные представления. При использовании SPT, ADO и XML вам придется полностью переоснастить свои схемы доступа к данным.
Увеличить размер существующего приложения для использования CursorAdapters так же просто, как и с удаленными представлениями; вместо этого вы просто заменяете объекты Cursor объектами CursorAdapter.
- С удаленными представлениями легко работать в дизайнерах форм и отчетов. Вы можете добавить его в DataEnvironment, а затем воспользоваться преимуществами визуальной поддержки, предоставляемой DataEnvironment: перетаскиванием полей для автоматического создания элементов управления, простой привязкой элемента управления к полю путем выбора его из поля со списком в окне свойств и т.д. SPT, ADO и XML не имеют такой визуальной поддержки.
CursorAdapters имеют ту же поддержку в DataEnvironment, что и удаленные представления.
- Удаленные представления легко создавать с помощью дизайнера представлений. Хотя в прошлом у него были серьезные ограничения, особенно при работе с представлениями, объединяющими более двух таблиц, VFP 8 устраняет большинство этих проблем и добавляет гораздо больше возможностей, таких как двустороннее редактирование: вы можете изменить код в окне SQL и увидеть эти изменения, отраженные в визуальной части дизайнера представлений. С SPT, ADO и XML это требует больше работы, так как вам нужно кодировать все: создание и закрытие соединения, выполнение операторов SQL SELECT и так далее.
VFP 8 включает в себя CursorAdapter Builder, который быстро устанавливает свойства, необходимые для извлечения и обновления данных. Он даже включает построитель SelectCmd, который, хотя и не так нагляден, как View Designer, позволяет вам выбирать, какие поля следует извлекать из удаленных таблиц, используя элемент управления «перемещение». •
- Базу данных бэкэнда легко обновлять с помощью изменений, сделанных в удаленных представлениях и наборах записей ADO. Предполагая, что свойства представления настроены правильно, вы просто вызываете TABLEUPDATE(). В случае ADO вы вызываете RecordSet.Update() или UpdateBatch(). С SPT и XML у вас есть куча ручной работы, чтобы передать обновления обратно.
Как мы видели ранее, выполнение обновлений с помощью CursorAdapter может быть таким же простым, как установка нескольких свойств, чтобы VFP выполнял всю работу, или вы можете иметь большую гибкость, указав, как обрабатываются удаления, вставки и обновления.
- Поскольку результирующий набор, созданный удаленными представлениями и SPT, представляет собой курсоры VFP, их можно использовать где угодно в VFP: в GRID, отчете, обработке в цикле SCAN и т. д. ADO и XML, с другой стороны, должны быть преобразованы в курсоры, прежде чем их можно будет использовать таким образом, что усложняет и увеличивает время обработки вашего приложения.
Результирующий набор CursorAdapter представляет собой курсор VFP, поэтому он имеет те же преимущества, что и удаленные представления и SPT. Более того, вы получаете курсор VFP, даже если источником данных являются ADO и XML, потому что CursorAdapter автоматически позаботится о преобразовании в курсор и из него.
- Поскольку оператор SQL SELECT удаленного представления определен заранее, вы не можете изменить его на лету. Хотя это нормально для обычной формы ввода данных, это может быть проблемой для запросов и отчетов. Возможно, вам придется создать несколько представлений из одного и того же набора данных, каждое из которых отличается выбранными полями, структурой предложения WHERE и т. д. Это не проблема с SPT, ADO или XML.
CursorAdapters не страдают от этой проблемы: вы можете легко изменить свойство SelectCmd, чтобы изменить, какие данные извлекаются и как.
- Вы не можете вызвать хранимую процедуру из удаленного представления, поэтому удаленному представлению необходим прямой доступ к базовым таблицам. Это может быть проблема с администраторами базы данных вашего приложения; некоторые администраторы баз данных считают, что доступ к данным должен осуществляться только через хранимые процедуры из соображений безопасности и по другим причинам. Кроме того, поскольку они предварительно скомпилированы на сервере, хранимые процедуры часто выполняются значительно быстрее, чем операторы SQL SELECT. С помощью SPT, ADO и XML вы можете при необходимости вызывать хранимые процедуры.
CursorAdapters также может использовать хранимые процедуры, просто установив SelectCmd по мере необходимости.
- Удаленные представления живут в контейнере базы данных, так что это еще один набор файлов, которые вам нужно поддерживать и устанавливать в системе клиента. Кроме того, когда вы открываете представление, VFP пытается заблокировать записи представления в DBC, даже если это ненадолго. Это может вызвать конкуренцию в загруженных приложениях, когда несколько пользователей могут одновременно пытаться открыть форму. Несмотря на то, что существуют обходные пути (копирование DBC на локальную рабочую станцию и использование ее, или, в VFP 7 и более поздних версиях, использование SET REPROCESS SYSTEM для увеличения времени ожидания блокировки), это то, что вам нужно запланировать. Еще одна проблема: если вы используете представление SELECT * для извлечения всех полей из определенной таблицы, а структура этой таблицы на сервере изменяется, представление недействительно и должно быть создано заново. Поскольку они не имеют ничего общего с DBC, ни одна из них не является проблемой для SPT, ADO и XML.
Поскольку они не живут в DBC, CursorAdapters также не имеют этих проблем.
- Поскольку они работают только с ODBC, удаленные представления и SPT застряли в модели прямого подключения данных «клиент-сервер». ADO и XML — предпочтительные механизмы для передачи данных между уровнями в многоуровневом приложении.
Поскольку CursorAdapters может создавать курсоры VFP из ADO или XML, они идеально подходят для использования на уровне пользовательского интерфейса многоуровневого приложения.
Резюме
Я думаю, что CursorAdapter — одно из самых больших и захватывающих улучшений в VFP 8, потому что он обеспечивает согласованный и простой в использовании интерфейс для удаленных данных, а также, как мы увидим в следующих статьях, он позволяет нам создавать повторно используемые классы данных. В следующем месяце мы рассмотрим особенности доступа к исходным или удаленным данным с помощью ODBC, ADO и XML. В следующем месяце мы рассмотрим создание повторно используемых классов данных и обсудим, как использовать CursorAdapters в отчетах.
Дуг Хенниг является партнером Stonefield Systems Group Inc. Он является автором отмеченных наградами инструментов Stonefield Database Toolkit (SDT) и Stonefield Query, соавтором книг «Что нового в Visual FoxPro 7.0» и «Руководства хакера по Visual FoxPro». 7.0», как от Hentzenwerke Publishing, так и от автора «Словаря данных Visual FoxPro» в серии Pros Talk Visual FoxPro от Pinnacle Publishing. Он был техническим редактором «Руководства хакера по Visual FoxPro 6.0» и «Основы» издательства Hentzenwerke Publishing. Дуг выступал на каждой конференции разработчиков Microsoft FoxPro (DevCon) с 1997 года, а также на пользовательских группах и конференциях разработчиков по всей Северной Америке. Он является Microsoft Most Valuable Professional (MVP) и Certified Professional (MCP). Интернет: www.stonefield.com и www.stonefieldquery.com Электронная почта: dhennig@stonefield.com
(Автор перевода Михаил Леменев)