Ну а теперь поработаем ручками.
Честно говоря, большого смысла начинать описания с работы курсор-адаптера с родными курсорами VFP я не нахожу, так как в большей степени он предназначен для работы с источниками данных, отличающихся и по природе, и по технологии от курсоров и таблиц VFP. Поэтому вернемся, для начала, к MySQL, достаточно быстро развивающемуся серверу и уже прочно укрепившемуся в Интернет, как чуть-ли не основная база для приложений.
Так как работать мы будем через ODBC, нам необходим хэндл (handle) соединения с базой данных MySQL. Можно заготовить заранее DSN в панели мэнеджера ODBC, можно прописать строку соединения ручками. Поскольку все решили делать ручками, так пусть они и поработают.
Замечание: при написании этих статей использовались:
- Apache Server /2.0.49 установленный на Windows 2000 Professional
- MySQL Server 4.0.18-nt там же
- База данных - реальная рабочая база данных "maardu"
Для начала пропишем строку соединения:
lcDSN="DRIVER=MySQL ODBC 3.51 Driver;"+;
"UID=root;"+;
"STMT=;"+;
"OPTION=16;"+;
"PASSWORD=;"+;
"SERVER=localhost;"+;
"DATABASE=maardu;"+;
"DESC="
и получим хэндл соединения:
lnConnHandle=SQLSTRINGCONNECT(lcDSN)
Создадим объект - инстанцию класса CursorAdapter -используя стандартную функцию CREATEOBJECT().
lo_CA=CREATEOBJECT("CursorAdapter")
На скриншоте справа показаны все свойства по умолчанию, которые созданы при простой инициализации субстанции класса.
Прежде всего установим алиас для курсора который создаст Visual FoxPro в объекте CursorAdapter.
lo_CA.Alias="cTestMySQL"
Поскольку мы используем тип источника данных "ODBC", то и присвоим соответствущему свойству DataSourceType объекта указанный тип:
lo_CA.DataSourceType="ODBC"
Далее, необходимо передать полученный хэндл соединения объекту CursorAdapter. Это делается с помощью свойства DataSource, которому в данном случае мы присваиваем имя переменной памяти, в котором хэндл хранится.
lo_CA.DataSource=lnConnHandle
Теперь самое важное - что мы желаем получить из нашей базы - пусть это будут наимванования автобусных маршрутов, обслуживающих город. Они хранятся в поле "blnames" таблицы "buslines". Для выборки используется простая команда:
"Select blnames FROM buslines"
Эту команду мы должны поместить в свойство SelectCmd нашего объекта на базе класса CursorAdapter.
lo_CA.SelectCmd="Select blnames FROM buslines"
Ну вот, вроде все и подготовлено, осталось только как-то вытащить данные из таблицы в курсор, который нам создаст объект CursorAdapter. Для этого используется метод CursorFill этого объекта.
lo_CA.CursorFill
Теперь соберем все до кучи, откроем новый программный файл, скопируем полученный листинг (естественно, что имена баз, таблиц и полей вы должны использовать из своего сервера) и запустим. Я надеюсь, что последние три команды не нуждаются в комментарии:
lcDSN="DRIVER=MySQL ODBC 3.51 Driver;"+;
"UID=root;"+;
"STMT=;"+;
"OPTION=16;"+;
"PASSWORD=;"+;
"SERVER=localhost;"+;
"DATABASE=maardu;"+;
"DESC="
lnConnHandle=SQLSTRINGCONNECT(lcDSN)
lo_CA=CREATEOBJECT("CursorAdapter")
lo_CA.Alias="Curfrommysql"
lo_CA.DataSourceType="ODBC"
lo_CA.DataSource=lnConnHandle
lo_CA.SelectCmd="Select blnames FROM buslines"
lo_CA.CursorFill
BROWSE
RELEASE lo_CA
SQLDISCONNECT(lnConnHandle)
И что же мы имеем в итоге? Такой вот результат.
То есть для просмотра таблиц хватает. Однако надобно и добавлять, и удалять и обновлять.
Для начала займемся обновлением.
Для того, чтобы мы могли обновить данные в исходной таблице нам нужно указать значения для ряда свойств объекта CursorAdapter, a именно:
Вот здесь есть один нюанс. Если посмотреть на описание UpdateCmdDataSource, то там недвусмысленно сказано, что это может быть символьный тип даных, и в принципе, если используется машинный источник данных, то мы можем присвоить этому свойству строку с командой SQL - sqlstringconnect([dsn=MySQL2CA;]), где и укажем этот DSN. Предлагаемый построитель VFP для объекта CursorAdapter так и делает.
Далее сказано, что это может быть пустая строка или .Null. и в этом случае CursorAdapter будет использовать источник данных из свойства DataSource.. Вот она - тонкость. Если мы сделаем это, и не оставим значения этого свойства по умолчанию, а возьмем и явно присвоим пустую строку или .Null.,
lo_CA.UpdateCmdDataSource=""/.Null.
то при попытке обновления данных мы получим сообщение об ошибке ("Connection handle is invalid").
Для того, чтобы все это заработало есть два варианта:
- мы вообще не упоминаем в коде ни UpdateCmdDataSource, ни UpdateCmdDataSourceType!
- используем в коде оба свойства и присваиваем в обязательном порядке свойству UpdateCmdDataSourceType значение "ODBC" и свойству UpdateCmdDataSource уже созданный хэндл соединения.
Пусть это будет так:
lo_CA.UpdateCmdDataSourceType="ODBC"
lo_CA.UpdateCmdDataSource=lnConnHandle
В итоге, для используемой мною базы данных и таблицы фрагмент кода, отвечающего за обновление данных может выглядеть так:
lo_CA.Tables="buslines"
lo_CA.KeyFieldList="ID"
lo_CA.UpdateNameList="ID buslines.id,BLNAMES buslines.blnames"
lo_CA.UpdatableFieldList="id,blnames"
lo_CA.UpdateCmdDataSourceType="ODBC"
lo_CA.UpdateCmdDataSource=lnConnHandle
или так:
lo_CA.Tables="buslines"
lo_CA.KeyFieldList="ID"
lo_CA.UpdateNameList="ID buslines.id,BLNAMES buslines.blnames"
lo_CA.UpdatableFieldList="id,blnames"
и это два рабочих варианта.
Поскольку при работе с CursorAdapter используется буфферизация, то необходимо позаботиться об установке SET MULTILOCKS и установить ее в ON
Новый листинг программы в предпочтительном варианте будет выглядеть так:
SET MULTILOCKS ON
lcDSN="DRIVER=MySQL ODBC 3.51 Driver;"+;
"UID=root;"+;
"STMT=;"+;
"OPTION=16;"+;
"PASSWORD=;"+;
"SERVER=localhost;"+;
"DATABASE=maardu;"+;
"DESC="
lnConnHandle=SQLSTRINGCONNECT(lcDSN)
? lnConnHandle
* вставим также код проверки работы этой программы,
* при необходимости можно снять комментарий и посмотреть
* что имеем в результате
*!*SQLEXEC(lnConnHandle, "SELECT BUSLINES.* FROM BUSLINES")
*!*RETURN
lo_CA=CREATEOBJECT("CursorAdapter")
lo_CA.Alias="Curfrommysql"
lo_CA.DataSourceType="ODBC"
lo_CA.DataSource=lnConnHandle
lo_CA.SelectCmd="Select buslines.* from buslines"
lo_CA.Tables="buslines"
lo_CA.KeyFieldList="ID"
lo_CA.UpdateNameList="ID buslines.id,BLNAMES buslines.blnames"
lo_CA.UpdatableFieldList="id,blnames"
llCursorFilled=lo_CA.CursorFill()
? "Is cursor filled? "
?? llCursorFilled
BROWSE
RELEASE lo_CA
SQLDISCONNECT(lnConnHandle)
А что же с удалением/вставкой? Измените явно тип обновления:
lo_CA.UpdateType=2
То есть данные должны обновляться через удаление/вставку.... Работает.
Стало быть для удаления записей и вставки новых больше ничего не надо? Именно так. В окне Browse пометьте запись на удаление. Запустите еще раз программу. Удалено. Запустите еще раз программу. Вставьте новую запись... Вставлена.
То есть для операций над данными необходимо прописать только 4 свойства:
И это действительно так. Будет продолжено!!!
|