Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2002.02.07;
Скачать: [xml.tar.bz2];

Вниз

Нужен совет в подходах работы с БД   Найти похожие ветки 

 
kserg@ukr.net   (2002-01-08 12:59) [0]

С Новым годом Всех! Хочу выяснить у уважаемых коллег какие есть
подходы в технике работы с клиент-серверной БД.
Поясню.
Один из подходов (пользуюсь им сам) следующий:
работа с таблицами только через TQuery (полный отказ от TTable).
Т.е. формирую запрос со всеми наворотами WHERE-GROUP-ORDER,
выполняю его и "гоню" в GRID.
Как правило, в GRID вытягиваю данные из нескольких связанных таблиц.
Соот-но операции Add/Edit в GRIDe делаю недоступными и выполняю их через
вспомаг.окношко, где есть все нужные поля при заполнении котр. использую
всякие "примочки" для ускорения-удобства ввода инфо юзерами.
Затем выполняю входной контроль данных
(как правило, чтобы ключевые поля не были пустыми)
и только после этого формирую соот-щий запрос Insert/Update.
После успешной операции остается только переоткрыть
рабочий набор данных
(сталкнулся с ситуациями, когда метод REFRESH не всегда срабатывал,
поэтому пришлось тупо делать TQuery.Close; TQuery.Open;)

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

Но, пользователям не всегда нравиться такая сложная схема.
Многие хотят вести правку прямо в GRIDe.

И здесь мне не совсем ясно, как реализовать такой подход
(правка прямо в GRIDe), когда запрос выполняется по 2-3-4 связанным таблицам?

Хотелось бы услышать, какие еще подходы работы получили распространение.

Заранее благодарен.
Сергей


 
Romkin   (2002-01-08 13:30) [1]

Для двухзвенки - подход практически единственно правильный, все так делают, разняться только проверки полей (иногда в триггере, со своими exception). Все остальное - тормознее, хотя и удобнее
Могу посоветовать TUpdateSQL - при включении CashedUpdates сам будет вгонять в базу, и запрос можно будет редактировать :-)) правда, вопрос, что делать с полями из других таблиц..., обычно lookup поля не селектишь, а организуешь в гриде
Но можно применять смешанно.
Можно также использовать связку TDataSetProvider + TClientDataSet, там делай, что хошь. Но в результате все равно приходишь к схеме Список - Форма редактирования, по OK - закачка.


 
panov   (2002-01-08 13:32) [2]

1. Объяснить пользователям, что если они хотят терять и перебивать свои данные по 10 раз, то можно сделать так, как они хотят.
2. Воспользоваться TTable, и все корректировки выполнять в транзакциях. После окончания спрашивать у пользователей, хотят ли они сохранить то, что напортили в БД, или нет.
3. Пользоваться UpdateSql...


 
kaif   (2002-01-09 01:00) [3]

Можно впролне надежно редактировать и в Grid-е. Нужно поставить UpdateSQL или заглушку какую-то вместо него, или вписать в него что-нибудь, чтобы не ругался, что нет соответствующих запросов, затем вписать в обработчик BeforePost самого DataSet код, создающий TQuery runtime и так можно кучу таблиц сразу апдейтить. В обработчике BeforePost можно в конце Abort вписать, чтобы не выполнялись тексты, вписанные в UpdateSQL.
Еще проще, если режим CashedUpdates использовать. Тогда можно все руками прописать.
Хотя неужели пользователю нужно апдейтить сразу множество таблиц?...


 
Desdechado   (2002-01-09 10:19) [4]

я извлекаю практически во всех формах данные через хранимые процедуры (просто очень навороченные запросы получаются), засовываю в грид, даю пользователю редактировать (иногда прямо в гриде, иногда отдельно), а сохраняю опять при помощи хранимой процедуры, которая распихивает все данные по нужным таблицам с нужными операциями (INS, DEL, UPD). Она же прописана во всех 3 SQL компонента UpdateSQL.
Очень удобный подход - все вынесено на сервер, клиентское приложение не заморочивается всеми нюансами.


 
Сергей Иванов   (2002-01-09 13:11) [5]

Полностью согласен с Desdechado. Romkin, почему же единственно правильный именно этот подход? Он скорее наиболее прост, т.к. позволяет обходится стандартными компонентами.
Может, я не прав, но зачем клиенту перечитывать базу, если все, что он внес в гриде (я использую в основном TStringGrid и TListView для этих целей) он может видеть прямо здесь, не отходя от кассы. Если хранимая процедура отработала успешно, то просто переписываем значения ячеек в гриде. Сложнее уведомить всех остальных об изменениях (используем своего рода callbacks для рассылки сообщений всем заинтерисованным клиентам), но это можно сделать. К тому же, для заполнения гридов и форм мне нужны просто связанные списки, например название фирм+заказы+дата заказа. Получим его при помощи IStrings и заполним грид - тем самым заставив сервер перебирать Query, а не сливать это на клиента и гонять его там. Не думаю, что оператору нужно знать ID записи, ее Relation и прочее. Заслав на сервер в процедуре всего пару-тройку уникальных параметров (которые позволят идентифицировать заказ на самом сервере) и изменение/дополнение/создание заказа в еще одной хранимой процедуре (имена товаров+кол-во; сервер сам найдет их ID, наличие на складе, вес, упаковку и т.д.) и вернет нам except - если нету или чего еще.


 
Сергей Иванов   (2002-01-09 13:19) [6]

PS.
"Почему именно связанные списки, ведь есть же база данных и запросы. Там ведь все связано" - сказал мне шеф.
"Потому что это дельфишные TTable(TQuery)+TDataset+TDataLink, тормозящие даже при простом пролистывании (не редактировании!) грида, модуль DBTables, модуль DB, и еще наверняка - BDE на клиенте". Клиент опухает, и намного. А в этом случае он пуст, как бамбук.


 
kaif   (2002-01-09 13:32) [7]

В любом случае стоит переносить все на сервер. Совершенно согласен. К тому же в хранимых процедурах легче администрировать доступ. Например, делаем:
GRANT UPDATE ON TABLE1 TO PROCEDURE PROCEDURE1;
GRANT UPDATE ON TABLE2 TO PROCEDURE PROCEDURE1;
GRANT UPDATE ON TABLE3 TO PROCEDURE PROCEDURE1;
Затем пользователю нужно только прописать один GRANT:
GRANT EXECUTE ON PROCEDURE PROCEDURE1 TO USER1;
К тому же можно прямо в процедурах использовать имя пользователя, причем в процедуре, которая делает SELECT, например:
FOR SELECT ... FROM TABLE1
WHERE USER=DOCUMENT_CREATOR
INTO ...
DO SUSPEND;
Для этого достаточно в таблице завести поле DOCUMENT_CREATOR и вписывать туда значение системной переменной USER в триггере перед вставкой.
Вообще не следует администрирование прав оставлять на самый последний момент - лучше продумать все это заранее.


 
evgeg   (2002-01-09 13:32) [8]

> И здесь мне не совсем ясно, как реализовать такой подход
(правка прямо в GRIDe), когда запрос выполняется по 2-3-4 связанным таблицам?

Можно, например сделать компонент TUpdateScript, который на каждое действие будет выполнять несколько запросов.
Симпатичен подход Desdechado, хотя процедур будет многовато.


 
Romkin   (2002-01-09 15:11) [9]

2Сергей Иванов
Постепенно начинает появлятся требование видеть не только то, что сам сделал, но и результаты работы других клиентов, а это быстрее всего перечитыванием (для стандартных компонент). То, как у тебя - все ручками... Мне, например, нравится MIDAS - тоже клиент пуст, и при этом все автоматом, ну почти все. А насчет callback... Тяжко - встает вопрос о синхронизации потоков (очередь уведомлений), о том, как показывать (пользователю не очень приятно, когда данные перечитываются как только надо), опять же возникнут вопросы типа "А почему ошибка? у меня в списке не занято..." (на другой станции уже заняли...) - опять же для проверки обращаешься к базе. ТАк что еще вопрос, что удобнее - постоянное обновление после редактирования или по уведомлению


 
Сергей Иванов   (2002-01-10 11:17) [10]

Конечно постоянное обновление удобнее. И проще в реализации. Но при количестве клиентов ~>5 начнаются тормоза. На чем бы не крутилась база.
Парус8 видел? Oracle8i+Delphi5. Интрефейс (для всего - и документов, и журналов, и...) - TreeView слева, два грида (один над другим) справа. Гриды - наследники TDBGrid. Так вот там больше всего времени (и траффика, и ресурсов сервера) занимает как раз перечитывание датасетов даже при простом листании TreeView. Скорее всего реализация такова: выбрали TreeNode -> Locate(MasterData) -> в нижнем гриде - DetailData перечитывается с сервера. При проходе по строчкам Master -> перечитывание Detail. И прочее, прочее, прочее :(
А ведь если вдуматься, чаще всего детальные данные и не нужны, как впрочем, и бОльшая часть основных. Как и связанное представление в 2-3 гридах - это просто неудобно для оператора. У меня операторы долбят по клаве не глядя на содержимое - товара, организации, контрагента - они это помнят как "отче наш". При необходимости - пжлста. Перечитаем Detail.
Вот такие вот дела. Мда... Много чего еще хотелось бы сказать :) да писАть лень :( Это тема для объемного разговора, если не статьи.


 
Romkin   (2002-01-10 11:55) [11]

Полностью согласен, чаще всего дает организация интерфейса: чем он красивее, тем больше тормозов. У меня давно интерфейс в виде простого списка, с фильтром (чаще всего по периоду), количество записей зависит от фильтра, если юзверь его убрал - сам виноват, что ждет несколько минут, в руководстве это помянуто. Результат - спокойная работа по модему. Обновление идет либо по кнопке, либо после редактирования. А детальные данные только по заказу, они действительно не нужны, всегда можно сделать еще список, в котором связка detail->master


 
kserg@ukr.net   (2002-01-10 12:01) [12]

Благодарю всех за интересную дискуссию
(теперь мне "пищи" для размышлений хватит на долго)
Отдельно хочу сказать спасибо >Romkin - выручает меня уже не первый раз.



Страницы: 1 вся ветка

Форум: "Базы";
Текущий архив: 2002.02.07;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.005 c
1-18894
maximf
2002-01-23 16:54
2002.02.07
Использование исходников VCL при отладке


1-18818
Filat
2002-01-24 16:08
2002.02.07
Как закрыть перед выходом из программы *.ini с использованием RxFormStorage?


3-18760
UnDISCOvery
2002-01-10 13:46
2002.02.07
Базы данных и графика в них !


14-18953
gun19456
2001-12-16 15:51
2002.02.07
Где найти хороший бесплатный хостинг для размещения программ ?


14-18978
vivus
2001-12-17 16:36
2002.02.07
Люди. по Дельфи есть сайт (этот). А про С++ (подобный на мастак.ру)?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский