FoxPro Club Главная

Конференция Решения Фотоальбом Сайт М.Дроздова Статьи Файловый архив Книга Visual FoxPro 9.0 Русский Help для Visual FoxPro
Пользователей: 9207
Вход
Пример клиент-серверного приложения - программа учета оргтехники. Visual FoxPro клиент + MS SQL Serv

Пример клиент-серверного приложения - программа учета оргтехники. Visual FoxPro клиент + MS SQL Server 7. Справочный файл, в связи с его размером (630Кб), доступен для опциональной загрузки отсюда: http://foxserver.nsvisual.com/download/other/computers_hlp.zip


 
Прислал: Дмитрий Орлов   Категория: Разное


Пример клиент-серверного приложения

От автора.

Уважаемые коллеги!

В последнее время на форуме прослеживается живой интерес к клиент-серверным приложениям, в частности к связке VFP-MSSQL, что подвигло меня данную публикацию.

Так же, моя профессиональная деятельность за последнее время несколько изменилась и я уже не являюсь VFP программером в полном смысле этого слова, так что эта публикация является отчасти и прощальным приветом всем вам, в особенности тем людям, с которыми я долгое время общался и которые несмотря ни на что любят и знают столь незаслуженно забытый нынче Visual Foxpro: Владимир Журавлев, Степанов Денис (HellRiser), Гринчишин Влад, Сергей Титов, Владимир Максимов, Кочкомбаев Тарас, Людмила, Жирнов Сергей, Насоновская Надя и многие другие.

Эти люди меня многому научили, за что им огромное спасибо.

Предупреждение.

Данный пример ни в коей мере не может служить эталоном по созданию CS приложений на VFP! Эту программу я написал, когда знакомился с MS SQL Server 7 (около 2х лет назад). Более того - это моя первая программа, использующая клиент-серверную технологию.

Ну и,самое главное, здесь используются только SPT функции, т.к. только они позволяют держать под абсолютным контролем удаленную БД, и нет ни слова о Remote View (я считаю, что не надо скрещивать два разных подхода к CS приложениям на VFP).

Тем не менее, приемы работы с данными, использованные здесь, достаточно показательны, и могут ответить на вопросы большинства интересующихся.

Программа не является учетной в понятии бухгалтерии, скорее, это обычная картотека для IT службы крупного предприятия.

Платформа.

Клиентская часть разрабатывалась и компилировалась под VFP6+SP5. Успешно работает под Win9xWin2000Pro(Eng & Rus)NT4 WS. Серверная часть - MS SQL Server 7+SP3 (так же испытывалась на MSDE1MSDE2000).

Недостатки и грабли.

Некоторые из перечисленных недостатков могли бы быть устранены перед публикацией, но я сознательно не стал этого делать, чтобы сохранить Ваше настороженное отношение к коду, а проще говоря - уберечь от бездумного копирования.

Именно после этого проекта я написал пакет классов для работы с удаленными данными (которые опубликованы здесь в "Решениях"), т.к. здесь в полной мере проявился недостаток процедурного программирования в отношении работы с функциями SQL pass trought (SPT), а именно:

  • Код обработки SPT функций "размыт" по тексту программы (в основном - сосредоточен в процедурах обмена данными)
  • Вследствие этого децентрализована обработка ошибок SPT функций, что так же не является хорошим тоном в программировании
  • Несколько некорректно обрабатываются транзакции. В принципе, это лечится установкой соответсвующего свойства соединения (SQLSETPROP(0, "Transaction", 2) && Режим ручной обработки транзакций), но здесь просто нет этой нужной строчки кода
  • Для возврата значений из хранимых процедур используется курсор, а не выходные (OUTPUT) параметры

Казалось бы - напиши универсальные процедуры и не "парься", однако, универсальность привела бы к неоправданной громоздкости этих самых процедур. Оптимальное решение - классы работы с SPT. К сожалению, к этому очевидному решению я пришел, когда уже была написана львиная доля кода и переписывать его уже не имело особого смысла - код работал. Так что учтите эти замечания, когда будете смотреть код.

Не смотря на это программа успешно эксплуатируется у нас в конторе и поныне. Говорят, что удобно.

Достоинства.

Кроме недостатков, программа обладает и достоинствами, причем немаловажными. Вот они:
  • Минимальный траффик, т.к. вся "грязная" работа выполняется сервером с помощью хранимых процедур (ХП), а клиенту перегоняется минимум необходимых данных
  • Использование ХП позволяет повысить степень защищенности данных на сервере, т.к. можно запретить непосредственный доступ пользователей к таблицам
  • Изменение структуры данных не приведет к изменению кода клиентской части, в случае, если не изменится интерфейс ХП
  • Подробная документация и интерактивная справка

Можно, конечно, напрячься и вычислить еще пару достоинств, но эти - основополагающие.

Сопроводительная документация.

К программе прилагается:

  • Createdb.sql - Скрипт генерации БД - после его выполнения Вы получите 100% работающую БД
  • Хранимые процедуры БД Computers .xls - Excel таблица с описанием ХП сервера
  • Computers_4.ER1 - ER модель базы данных (ErWin 4)
  • Readme.txt - описание программы, процедуры ее установки и настройки DSN (в файле справки это тоже есть, да еще с иллюстрациями)
  • Computers.hlp - файл справки
Справочный файл, в связи с его размером (630Кб), доступен для опциональной загрузки отсюда: http://foxserver.nsvisual.com/download/other/computers_hlp.zip

Как сгенерить БД.

Краткая инструкция по генерации БД (для успешной работы необходимо обладать правами DBcreator на MSSQL):

  1. Запустить Query Analyser
  2. В окне команд написать: CREATE DATABASE Computers
  3. Нажать F5
  4. Будет создана БД Computers
  5. Открыть скрипт генерации БД (Меню Open...)
  6. Сделать активной новую БД (выпадающий список БД)
  7. Нажать F5
  8. В результате должны быть созданы все объекты БД, и таблицы проинициализированы системными записями
Если будут проблемы - сообщите. Попробуем решить.

Если же все в порядке - создайте DSN и можно запускать программу. Обязательно прочтите Readme.txt !!!

Опять от автора.

Прошу не судить строго. Буду рад конструктивной критике, желательно прямо здесь, в разделе - чтобы другие посетители были в курсе.

Буду очень рад, если это все кому-нибудь поможет. С уважением, Орлов Дмитрий aka Jimmy.

 
Сделайте оценку этого решения Плохо Удовлетворительно Так себе Хорошо Отлично Текущая оценка: (4.842) Вложение [316.98]kb
Дополнения пользователей
Пример клиент-серверного приложения - программа учета оргтехники. Visual FoxPro клиент + MS SQL Serv
[+][?]
Соколов Н. Г.
06.11.02 11:06:10

У меня почему-то считывается битый архив размером 22,4KB. Это мои проблемы или архив действительно
неправильно создан?
Николай.
Дмитрий Орлов
06.11.02 11:18:27

Я проверил закачку - все ОК. Скачалось все и ZIP-тест прошел на "ура".
Соколов Н. Г.
07.11.02 19:52:03

Дома тоже все нормально, это проблемы на работе. Спасибо.
Aijik
26.11.02 18:46:12

Jimmy, убедительная просьба решить что-нибудь с размещением некоторых графических файлов проекта.
Они в проекте имеют абсолютный путь пакета битмапов из Visual Studio 6 (т.е. C:\Program
Files\...Visual Studio\...Graphics\... ля-ля тополя - что-то в этом духе.). К сожалению, у меня не
стоит VS6 и на VFP7 проект отказывается компилироваться - не может найти более десятка картинок.
Можно, конечно, их все их проекта исключить или попытаться найти их вручную, но их ведь очень
много, причем они в VS6 лежали в разных директориях, к тому же, наверняка кое-чего просто нет в
поставке VFP7. Нельзя ли все эти картинки перенести в Computers.sql\Images в добавок к тем
картинкам, которые там уже есть?

С уважением,
Aijik
 
Дмитрий Орлов
27.11.02 10:05:17

Сделаю. К 1 декабря.
Дмитрий Орлов
27.11.02 11:34:27

Было время - сделал сегодня (27 ноя).
Однако, из-за тупизны VFP Project Manger & Class\Form Designer пришлось ручками указать картинки,
несмотря на то, что пути в свойствах Icon | Picture были правильными. Вероятно и вам придется это
проделать.
Николай Дмитриев
02.12.02 02:57:50

А как сгенерировать БД под MSDE2000 ?
После установки MSDE никакой Query Analyser не нашел. Если можно поподробнее, с SQL сервером я дел
еще не имел - для меня это новое.
Дмитрий Орлов
02.12.02 10:07:07

MSDE любых версий поставляется без клиентских утилит. Эти утилиты можно установить с
дистрибутивного диска MSSQL соответсвующей версии (кстати, с MSDE1 & MSSQL7 лучше работать с
помощью утилит MSSQL2000 - удобнее) или использовать иснтрументы MS Visual Studio.
Евгений Абрамов
27.12.02 07:13:43

Полгода занимаюсь разработкой клиет-серверных приложений.
Это очень мало, чтобы постичь все тонкости этого дела. Но все больше склоняюсь к тому, чтобы
отказаться от использования Remote View, слишком криво это работает, одна команда Refresh()
вызывает геморр.  Поэтому соглашусь с автором этой проги в том, что "Оптимальное решение - классы
работы с SPT".

Владимир Максимов
08.01.03 14:29:39

Интересно, это результат обновления или просто никто не копался глубоко в проекте? Однако:

1.Нет скрипта создания View с именем vwFullCMarkList

2.Недостаточно выдать сообщение типа "Ошибка соединения" в случае если SQLExec()=-1. Необходимо по
возможности выдать сообщение об ошибке самого сервера. Это сообщение можно достать используя
функцию AERROR(). Сбственно из-за этого я потратил массу времени пока докопался, что не хватает
View.

3.Ну и до кучи: Для форм пошагового редактирования (в общем случае - для форм у которых объекты
наложены один на другой)
удобнее использовать PageFrame без закладок (PageFrame.Tabs=.F.), а не набор контейнеров. С точки
зрения пользователя разницы никакой, но для программиста разница огромная.

Дмитрий Орлов
13.01.03 10:38:52

Спасибо Владимир.
Действительно, у меня (вернее в ErWin) были проблемы с вьюшками, поэтому я их создал вручную прямо
на сервере и они не заскриптованы в Er модели. Я кину скрипт для VIEW прямо сюда:

CREATE VIEW vwCompStat
AS
SELECT CP.IDmark, CM.IDtype, UL.IDdepart, SP.IDsupplier
	FROM  Computer CP, UserList UL, ComputerMark CM, Supplier SP,CompUser CU
	WHERE CU.IDcomp = CP.IDcomp 
		AND CP.IDmark = CM.IDmark 
		AND CU.IDuser = UL.IDuser 
		AND CP.IDsupplier = SP.IDsupplier 
		AND CU.LastOwner = 1

GO
CREATE VIEW dbo.vwFullCMarkList
AS
SELECT dbo.ComputerType.IDtype, 
    dbo.ComputerType.Name AS Type, dbo.ComputerMark.IDmark, 
    dbo.ComputerMark.Name AS Mark
FROM dbo.ComputerType INNER JOIN
    dbo.ComputerMark ON 
    dbo.ComputerType.IDtype = dbo.ComputerMark.IDtype
GO
CREATE VIEW dbo.vwFullCOwnersList
AS
SELECT dbo.Computer.IDcomp, dbo.Computer.LabelNo, 
    dbo.Computer.SerialNo, dbo.ComputerMark.Name AS Mark, 
    dbo.UserList.Name AS UserName, dbo.UserList.IDuser, 
    dbo.UserList.NoRoom, dbo.ComputerType.Name AS Type, 
    dbo.ComputerType.IDtype, dbo.ComputerMark.IDmark, 
    dbo.UserList.IDdepart, dbo.Computer.DatePur, 
    dbo.Department.Name AS Department
FROM dbo.Computer INNER JOIN
    dbo.ComputerMark ON 
    dbo.Computer.IDmark = dbo.ComputerMark.IDmark INNER JOIN
    dbo.CompUser ON 
    dbo.Computer.IDcomp = dbo.CompUser.IDcomp INNER JOIN
    dbo.UserList ON 
    dbo.CompUser.IDuser = dbo.UserList.IDuser INNER JOIN
    dbo.ComputerType ON 
    dbo.ComputerMark.IDtype = dbo.ComputerType.IDtype INNER JOIN
    dbo.Department ON 
    dbo.UserList.IDdepart = dbo.Department.IDdepart
WHERE (dbo.CompUser.LastOwner = 1)
GO
CREATE VIEW dbo.vwFullPMarkList
AS
SELECT dbo.DeviceType.IDtype, dbo.DeviceType.Name AS Type, 
    dbo.DeviceMark.IDmark, 
    dbo.DeviceMark.Name AS Mark
FROM dbo.DeviceType INNER JOIN
    dbo.DeviceMark ON 
    dbo.DeviceType.IDtype = dbo.DeviceMark.IDtype
WHERE (dbo.DeviceType.External = 1)
GO
CREATE VIEW dbo.vwFullPOwnersList
AS
SELECT dbo.Peripheral.IDhard, dbo.Peripheral.LabelNo, 
    dbo.Peripheral.SerialNo, dbo.DeviceMark.Name AS Mark, 
    dbo.UserList.IDuser, dbo.UserList.Name AS UserName, 
    dbo.UserList.NoRoom, dbo.DeviceType.Name AS Type, 
    dbo.DeviceType.IDtype, dbo.DeviceMark.IDmark
FROM dbo.DeviceMark INNER JOIN
    dbo.Peripheral ON 
    dbo.DeviceMark.IDmark = dbo.Peripheral.IDmark INNER JOIN
    dbo.PerUser ON 
    dbo.Peripheral.IDhard = dbo.PerUser.IDhard INNER JOIN
    dbo.UserList ON 
    dbo.PerUser.IDuser = dbo.UserList.IDuser INNER JOIN
    dbo.DeviceType ON 
    dbo.DeviceMark.IDtype = dbo.DeviceType.IDtype
WHERE (dbo.PerUser.LastOwner = 1)
GO
CREATE VIEW dbo.vwFullUserList
AS
SELECT dbo.Department.IDdepart, dbo.Department.Name, 
    dbo.UserList.IDuser, dbo.UserList.Name AS UserName, 
    dbo.UserList.NoRoom
FROM dbo.Department INNER JOIN
    dbo.UserList ON 
    dbo.Department.IDdepart = dbo.UserList.IDdepart
GO
CREATE VIEW vwPerStat
AS
SELECT PR.IDmark, DM.IDtype, UL.IDdepart, SP.IDsupplier
	FROM  Peripheral PR, UserList UL, DeviceMark DM, Supplier SP,PerUser PU
	WHERE PU.IDhard = PR.IDhard
		AND PR.IDmark = DM.IDmark 
		AND PU.IDuser = UL.IDuser 
		AND PR.IDsupplier = SP.IDsupplier 
		AND PU.LastOwner = 1

GO
CREATE VIEW dbo.vwProcList
AS
SELECT dbo.InternalDevice.IDcomp, dbo.InternalDevice.ExtData, 
    dbo.DeviceMark.IDmark, 
    dbo.DeviceMark.Name AS Mark
FROM dbo.DeviceType LEFT OUTER JOIN
    dbo.DeviceMark ON 
    dbo.DeviceType.IDtype = dbo.DeviceMark.IDtype RIGHT OUTER
     JOIN
    dbo.InternalDevice ON 
    dbo.DeviceMark.IDmark = dbo.InternalDevice.IDmark RIGHT OUTER
     JOIN
    dbo.Computer ON 
    dbo.InternalDevice.IDcomp = dbo.Computer.IDcomp
WHERE (dbo.DeviceType.IDtype = 14)
GO
CREATE VIEW dbo.vwRamList
AS
SELECT dbo.InternalDevice.IDcomp, dbo.InternalDevice.ExtData, 
    dbo.DeviceMark.Name AS Mark
FROM dbo.InternalDevice INNER JOIN
    dbo.DeviceMark ON 
    dbo.InternalDevice.IDmark = dbo.DeviceMark.IDmark INNER JOIN
    dbo.DeviceType ON 
    dbo.DeviceMark.IDtype = dbo.DeviceType.IDtype
WHERE (dbo.DeviceType.IDtype = 15)
GO


Шумеев Сергей
17.02.03 21:52:17

Дмитрий! Как я понял все изменения в БД на сервере через хранимые процедуры. Подскажите как быть
если:
1. Полей в таблицах более 10, иногда до 100.
2. БД достаточно динамична по времени, какие-то поля удаляются, еще больше добавляется новых.

Такое количество параметров в ХП и их модификация каждый раз при изменении структуры БД - не самое
красивое решение...
              С уважением Шумеев С.       
Дмитрий Орлов
18.02.03 16:56:53

Вариантов, собственно, немного.
1. Использовать RemoteView
2. Продолжать терзать SQL Pass Trougth функции, но к реализации бизнес-логики на сервере подойти с
умом.

Что это значит?
А значит это вот что:

-- через ХП можно работать только с ключевыми таблицами, к остальным дать полный доступ (тоже не
лучший вариант в плане безопасности, но вполне жизнеспособный)

-- использовать связку View - SP, т.е. пользователи работают только с View, а все изменения -
через ХП, которые "заточены" на структуру View. Таким образом, View будут скрывать от клиента
постоянные изменения структур (т.е. будут условно-постоянными), а ХП, привязанные к
представлениям, так же не будут страдать от этих изменений.

-- кроме того, можно работать с версиями процедур, которые создаются каждый раз при изменении
данных, т.е. "старые" клиенты работают, как и работали (с прошлыми версиями ХП), а новые - уже с
новыми. Естественно - нужно быть очень бдительным.

-- можно работать посредством временных таблиц, данные из которых "подхватывают" непараметрические
ХП, которые и раскидывают их по реальным таблицам. Тоже вариант не ахти, но имеет право на
существование.

-- просто дать клиентам права на все таблицы и оперировать динамически формируемыми SQL запросами.
Этот вариант - источник больших проблем.

ИМХО конечно.
[Дополнить]



© 2000-2017 Fox Club 
При размещении любых материалов с сайта на других ресурсах- прямая ссылка на www.foxclub.ru обязательна
Яндекс.Метрика