![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Совместное использование одной таблицы [MSSQL]
DeadMeat © (2006-11-20 16:57:00)Здравствуйте.
Я в базах новичек, поэтому сильно не бейте (хотя бы не ногами).
Есть:
СУБД Microsoft SQL 2000 (SP3)
ADO (компоненты ADOConnection и ADODataSet)
EhLib (компоненты MemTableEh и DBGridEh)
Таблица (просто список людей)
Несколько пользователей (работники)
Надо:
При совместной работе с одной таблицей двух и более пользователей разруливать ситуацию с обновлением информации.
Понимаю, что сказал бред. Попробую пояснить.
Допустим пользователь ЮЗЕР1 выбрал первую запись для редактирования (первая - это образно, первая сверху). Отредактировал и сохранил обратно в базу (MemTableEh.Edit, MemTableEh.Post, MemTableEh.ApplyUpdates(0)). Если после этого пользователь ЮЗЕР2 решит отредактировать эту же запись, то выскочит ошибка "Не удается найти строку для обновления.......". Погуглив выяснилось, что проблема в том, что после редактирования найти эту запись ЮЗЕР2 уже не может, т.к. критерии поиска уже другие. Соответственно
введя первичный ключ и добавив в AfterOpen задание параметра Update Criteria значением adCriteriaKey проблема решается. Но лишь проблема появления ошибки. Т.е. получается, что ЮЗЕР2 не видя то, что записал в базу ЮЗЕР1 запишет туда что-нить свое. А вот хотелось бы отобразить изменения, которые сделал ЮЗЕР1 для всех остальных пользователей. Вводить дополнительно сетевую часть (передавать всем броадкастом информацию об обновлениях) не очень хочется. Каждый раз делать Requery перед редактированием любой записи тоже. Может есть способ еще? Как определить, что "вот эту"запись изменили, и что "вот эту"запись надо обновить? Пробовал проверять RecordStatus на rsModified - не помогло.
ЗЫ. Вполне вероятно, что гдето написал бред, но я только начал эту область осваивать.
ЗЗЫЫ. Пишу в BDS2006.
clickmaker (2006-11-21 11:02:00) [101]
> Но вот как после обновления попросить сервер вернуть только
> одну эту измененную запись, а не весь набор целиком?
Теоретически можно завести некий сервис для оповещения. Клиент, обновивший запись шлет ему сообщение, что мол обновил запись с ID=233, а сам сервер рассылает его подключенным клиентам.
Но тогда клиент должен отдельным запросом получить только одну эту запись и обновить какой либо список. Грид же обновляется только целиком, поскольку сам он списка не содержит, а просто отображает датасет.
Т.е. нужен датасет, в котором можно поменять 1 запись. Например, датасет в памяти.
DeadMeat (2006-11-21 10:53:00) [102]
> clickmaker © (21.11.06 09:59) [13]
Общую схему я понял. Встает вопрос об обновлении несколько в другом смысле. Получается, что обновление надо будет все таки делать по таймеру. Это ладно. Смиримся. Вынесем в настройки. Но вот как после обновления попросить сервер вернуть только одну эту измененную запись, а не весь набор целиком?
> Sergey13 © (21.11.06 10:06) [14]
Хмм... Спасибо. Учту. Надо будет проверить. Может нужда в EhLib отпадет и вовсе.
Sergey13 (2006-11-21 10:06:00) [103]> [12] DeadMeat © (21.11.06 09:57)
> Да и в принципе, основной причиной выбора MemTableEh в связке
> между DBGridEh и ADODataSet был пропорциональный ScrollBar
> (вертикальный). Почему то без него я этого добиться не смог.
Скорее всего нужно было закачать все данные возвращаемые запросом на клиента. Т.е. сделать ADODastaSet.Last (или что-то вроде этого - я с АДО не работал). Плюс у гридовского скролбара Tracking выставить в истину.
clickmaker (2006-11-21 09:59:00) [104]
> [8] DeadMeat © (20.11.06 23:29)
> Вот заведу я это поле в таблице. Каждая запись будет иметь
> еще одно дополнительное поле. ЮЗЕР1 открыл запись для редактирования.
> Перед этим записали в это поле 1 (например). Как ЮЗЕР2 сможет
> считать значение этого поля, когда оно изменилось?
Ну как... юзер1 поменял что-то, нажал ОК. Запись закоммитилась, блокировку сняли. Теперь она доступна другим, уже с измененными данными.
Другое дело - это оповещение об изменении. Тут уже зависит от критичности по времени.
В билетной системе я делал обновление схемы зала по таймеру. Интервал выбирает пользователь, а может вообще выключить. Но тогда при попытке продать уже занятое место просто вылезет сообщение.
DeadMeat (2006-11-21 09:57:00) [105]
> Sergey13 © (21.11.06 08:58) [11]
EhLib 4.1 Build 4.1.4 Russian version
Когда покупал на тот момент была последней (покупал не давно).
> Плюс к этому, почему после изменения одним юзером другой
> не может изменить ту же запись?
Сейчас ЮЗЕР2 может изменить запись, скорректированную ЮЗЕР1. Update Criteria равный adCriteriaKey и первичный ключ спасли. Без этого было только то сообщение, которое я привел ("Не удается найти строку для обновления......."), ведь ЮЗЕР2 уже не может найти ту запись, т.к. без ключа поиск можно было сделать лишь по другим полям, а они уже изменились. Почему не выдавалось другого сообщения - я не знаю.
По поводу механизма, могу лишь сказать, что все изменения (как я понял) отсылаются в DataSetDriverEh скопом (после ApplyUpdates), который затем отслыает их в ADODataSet. Хотя конечно могу и ошибаться. В моем случае, я включил CachedUpdates и FetchAllOnOpen. Т.е. все данные я забираю в память целиком, а не кусками выкачиваю с сервера. Просто на стадии разработки не хотелось заморачиваться с "подкачкой" данных. Мне казалось, что проще пока будет все отладить так, а потом уже (при надобности) делать "подкачку" с сервера порциями. Да и в принципе, основной причиной выбора MemTableEh в связке между DBGridEh и ADODataSet был пропорциональный ScrollBar (вертикальный). Почему то без него я этого добиться не смог.
Sergey13 (2006-11-21 08:58:00) [106]> [10] DeadMeat © (21.11.06 08:38)
А EhLib у тебя какая? Щас почитал про 4, там вроде МемТабл - это практически некий аналог CDS, раньше вроде был попроще (но и с тем я не работал 8-). Т.е. непонятно как (механизм) изменяется база.
Плюс к этому, почему после изменения одним юзером другой не может изменить ту же запись? Первичный ключ меняется что-ли? Если запись просто изменена и не закомичена, то должно вроде бы другое сообщение вылезти (типа: запись была изменена другим пользователем).
DeadMeat (2006-11-21 08:38:00) [107]
> ЮЮ © (21.11.06 04:04) [9]
Ну тут несколько иначе. ЮЗЕР1 сделал запись. Посидели... поболтали. Тут ЮЗЕР1 просит ЮЗЕР2 сделать еще изменения, которые он забыл сделать. А просит, потому что ему надо выйти. Ну просто попросил. Вот и явный пример. Это только один пример. Но основная проблема тут в принципе в том, чтобы отобразить сделанные изменения.
ЮЮ (2006-11-21 04:04:00) [108]
> Таблица (просто список людей)
> Несколько пользователей (работники)
Как вообще возникает ситуация, что 2 разных работника пытаются одновременно ввести совершенно разную информацияю для просто человека? Даже если они не пересекутся по времени, то информация с точки зрения одного из работников будет неверная.
DeadMeat (2006-11-20 23:29:00) [109]
> clickmaker © (20.11.06 17:42) [5]
> поле завести в таблице.
Или я просто под вечер не соображаю или что. Но вот щас подумал и вопрос возник.
Вот заведу я это поле в таблице. Каждая запись будет иметь еще одно дополнительное поле. ЮЗЕР1 открыл запись для редактирования. Перед этим записали в это поле 1 (например). Как ЮЗЕР2 сможет считать значение этого поля, когда оно изменилось? Опять же вопрос про обновление данных. Целиком обновлять или как? Или просто завести отдельную таблицу не большого размера и в ней хранить запись типа:
TableName | RecordNum
---------------------
TABLE1 | 1
TABLE2 | 3
Смысл в том, что таблица не большая и вполне можно (хотя мне и не нравится такой способ) делать Requery или даже закрывать и открывать по новой датасет.
Что посоветуете?
Kolan (2006-11-20 23:22:00) [110]Я тоже новичок в бд, но разве это не забота сервера разрулить ситуацию?
DeadMeat (2006-11-20 23:16:00) [111]
> clickmaker © (20.11.06 17:42) [5]
> поле завести в таблице. Типа user_id или session_id
> или вообще spid (зависит, как у вас там работа с пользователями)Если
> оно не нулевое, значит запись занята
А... Другими словами все надо делать ручками. Понятно. Я просто думал есть какие способо через методы/свойства ADO и самого MSSQL. Но по всей видимости быстрее и проще всего будет руками все организовать.
Ну чтож... раз другого выхода нет - будем делать так.
Большое спасибо за информацию...
clickmaker (2006-11-20 17:42:00) [112]
> Т.е. как другим пользователям "объяснить", что "вот эта"
> запись заблокирована. Думаю осуществив этот механизм, можно
> сделать обновление именно "этой" записи после снятия блокировки.
поле завести в таблице. Типа user_id или session_id или вообще spid (зависит, как у вас там работа с пользователями)
Если оно не нулевое, значит запись занята
DeadMeat (2006-11-20 17:38:00) [113]
> Sergey13 © (20.11.06 17:01) [1]
> А при чем тут MemTableEh? Какова ее роль?
Он для "нормального" отображение данных в DBGridEh. Сортировка, отображение денег, пропорциональная полоса прокрутки ну и еще там по мелочи. С ним проще мне кажется.
> clickmaker © (20.11.06 17:05) [3]
> Для особо критичных данных иногда применяют следующее. Грид
> редактировать запрещают вообще. Только специальной формой.
> При открытии формы запись блокируется. Все остальные после
> этого получают либо отлуп, либо предложение открыть инфу
> для чтения. Эта идея с успехом используется в офисных приложениях
> (ворд, эксель).Форма закрылась - блокировку снимаешь
Ну собсна у меня данные как раз отдельной формой и редактируются. Вот только вопрос как без этого дополнительного сервиса заблокировать запись, чтобы ЮЗЕРх это "понял". Т.е. как другим пользователям "объяснить", что "вот эта" запись заблокирована. Думаю осуществив этот механизм, можно сделать обновление именно "этой" записи после снятия блокировки.
В любом случае, благодарю за ответы.... Если есть еще мысли - буду рад.
clickmaker (2006-11-20 17:05:00) [114]Для особо критичных данных иногда применяют следующее. Грид редактировать запрещают вообще. Только специальной формой. При открытии формы запись блокируется. Все остальные после этого получают либо отлуп, либо предложение открыть инфу для чтения. Эта идея с успехом используется в офисных приложениях (ворд, эксель).
Форма закрылась - блокировку снимаешь
clickmaker (2006-11-20 17:02:00) [115]
> DeadMeat © (20.11.06 16:57)
Знакомая проблема, ага.
Но решений, увы, кот наплакал. Ты их практически почти перечислил. Т.е. либо есть некий сервис, который оповещает остальных, что некто Вася поменял запись 1. После 2 варианта. Либо переоткрытие датасета, либо вообще не используется грид, а например ListView. Тогда можно индивидуально управлять записями по ID.
Еще вариант, если записей не слишком много, и жесткий риалтайм не нужен, то по таймеру обновлять табличку на клиенте.
Sergey13 (2006-11-20 17:01:00) [116]А при чем тут MemTableEh? Какова ее роль?
Вопрос об обновлении данных, отредактированных другим юзером, обсуждается каждую неделю. Каждый раз это признается бессмысленной тратой ресурсов в 99.9% случаев.