Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Совместное использование одной таблицы [MSSQL]


Страницы:   1 2 3 4 5 6

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.


Anatoly Podgoretsky   (2006-11-23 11:09:00) [81]

> clickmaker  (23.11.2006 10:35:31)  [31]

У блокировок обычный минус - всем хана, даже некоторые аггрегатные функции не сможешь выполнить.


Anatoly Podgoretsky   (2006-11-23 11:08:00) [82]

> clickmaker  (23.11.2006 10:19:28)  [28]

Это тоже блокировка, да и название говорит об этом.


Anatoly Podgoretsky   (2006-11-23 11:07:00) [83]

> clickmaker  (23.11.2006 10:10:26)  [26]

Я не знаю, что ты предлагал, только термин блокировка по отношению к базам имеет одназначное толкование.


Anatoly Podgoretsky   (2006-11-23 11:07:00) [84]

> clickmaker  (23.11.2006 10:17:27)  [27]

Вот это блокировка и есть


ANB   (2006-11-23 11:01:00) [85]


> каких минусов?
>
> и растолкуйте мне тупому, что же это за магическое резервирование
> такое?
> Может снизойдет на меня просветление

Самые элементарные минусы :
1) пока транзакцию, меняющую это поле на статус "Заблокировано" не закоммитишь, никто этой блокированности не увидит. Сие может привести к одновременной "Блокировке" двумя и более пользователями.
2) В случае сваливания клиента/сервера "блокированные" записи так такими и остануться. Значит придется изобретать всякие хитрые кнопки по аварийному разблокированию, которыми начнут пользоваться не по назначению и т.д.
Короче, я этот способ уже юзал - он довольно простой на первый взгляд, но грабли я все собрал :) Учись на моих ошибках :)
Ликбез по резервированию :
Возьмем для примера склад.
Есть остаток товара на складе, в минус его загонять нельзя. Несколько операторов шпандорят накладные. Есно, нельзя допустить, чтобы товара выписали больше, чем на складе. Чтобы этого не допустить, когда вводишь строку с товаром, запрошенное количество от отстатка минусуется и переводится в резерв (есть несколько способов реализации - тута можно поспорить). Далее готовую накладную можно либо провести, либо откатить нафиг. В первом случае резерв просто минусуется, во втором - резерв приплюсовывается обратно к остатку.
Нечто подобное реализуется и при работе билетного кассира - там места имеют несколько статусов - свободно, резерв, продано. При заказе билета они сначала резервируются, чтобы другой кассир не мог продать, а уже при их оформлении продаются. Резерв можно вернуть обратно в свободные при отказе от покупки билета или если кассир заснул. Перед продажей, есно проверяется, находится ли место в статусе резерв за этим кассиром.


clickmaker   (2006-11-23 10:35:00) [86]


> [30] ANB ©   (23.11.06 10:33)
> ИМХО : изобретать велосипед с блокировкой через доп.поле
> - вчерашний век. У этого метода есть целая куча минусов.
> Оправдана работа только с резервированием

каких минусов?

и растолкуйте мне тупому, что же это за магическое резервирование такое?
Может снизойдет на меня просветление


ANB   (2006-11-23 10:33:00) [87]

ИМХО : изобретать велосипед с блокировкой через доп.поле - вчерашний век. У этого метода есть целая куча минусов.
Оправдана работа только с резервированием, но это совсем другая тема.


ANB   (2006-11-23 10:30:00) [88]

Автору - у тебя уже все готово практически.
Надо только добавить следующую фичу :
Перед редактированием (подъемом формы на редактирование) нужно изменяемую запись перечитать с блокировкой.
Решится 2 задачи :
а) в форме будут свежие данные
б) сервером запись будет заблокирована и другой юзер ее открыть не сможет (тут возможны вариации с предложением открыть на чтение, обработав ошибку).
в оракле это делается элементарно : select for update
в мс скл должна быть подобная фича (где то я про нее читал).
К сожалению, я не нашел в ADO метода для рефреша одной записи да еще и с блокировкой, в ОДАКЕ это сделано явно, там и запрос настроить ручками можно. Впрочем, ща спецы придут - подскажут.
Если никак - то можно редактировать не основной набор данных, а свежезачитанный (надеюсь искусственные ключи в таблицах есть). А так как гридовые данные все равно в локальной кэше сидят, то сможешь изгальнуться обновить их, не отправляя на сервер.


clickmaker   (2006-11-23 10:19:00) [89]

Забыл добавить. Если кто-то другой попытается открыть заказ
if (LockUser_ID IS NOT NULL)
 'Заказ уже редактируется пользователем LockUser_ID. Можете открыть только для чтения'

чем не решение?


clickmaker   (2006-11-23 10:17:00) [90]


> Сначала запись резервируется

update Orders set LockUser_ID = User_ID  -- перед открытием заказа кассиром User_ID

> потом редактируется

update Orders set что-то where Order_ID = @OrderId

> возращается из резерва

update Orders set LockUser_ID = null where Order_ID = @OrderId

или я опять "полный бред" пишу?


clickmaker   (2006-11-23 10:10:00) [91]


> [25] Anatoly Podgoretsky ©   (23.11.06 10:06)
> > clickmaker  (23.11.2006 10:03:24)  [24]
>
> Запись не блокировать, а резервировать для операции, стандартное
> решение для кассиров.
> Сначала запись резервируется, потом редактируется, потом
> в или возращается из резерва или операция завершается нормально

а я что предлагал?
Или я чего-то не понял, или мы просто разные термины пользуем


Anatoly Podgoretsky   (2006-11-23 10:06:00) [92]

> clickmaker  (23.11.2006 10:03:24)  [24]

Запись не блокировать, а резервировать для операции, стандартное решение для кассиров.
Сначала запись резервируется, потом редактируется, потом в или возращается из резерва или операция завершается нормально.
Всегда известно, кто и когда и никаких конфликтов и блокировок.


clickmaker   (2006-11-23 10:03:00) [93]


> [23] Anatoly Podgoretsky ©   (23.11.06 09:56)
> > clickmaker  (23.11.2006 09:49:22)  [22]
>
> Есть - это резервирование

?


Anatoly Podgoretsky   (2006-11-23 09:56:00) [94]

> clickmaker  (23.11.2006 09:49:22)  [22]

Есть - это резервирование


clickmaker   (2006-11-23 09:49:00) [95]


> >clickmaker ©   (21.11.06 09:59) [13]
> >Ну как... юзер1 поменял что-то, нажал ОК. Запись закоммитилась,
> блокировку сняли. Теперь она доступна другим, уже с измененными
> данными.
>
> Если дом построить на трясине, то, действительно, потом
> придется прилагать гигантские усилия, чтобы он не рухнул
> и не уплыл..
>
> Я извиняюсь перед Мастером, но все же задам 2 вопроса:
>
> 1) Вы знакомы с понятием "транзакции" и "взаимовлияние транзакций"
> ?
> и
> 2) в какой это предметной области Вы городите всю эту чушь
> ?


причем тут транзакции?
простой пример: есть заказ. Есть 2 кассира, которые могут его поменять. Например, согласно пожеланию клиента. Если один кассир его откроет и начнет долго и мучительно выяснять у клиента, а что собственно он хочет, то о каких вообще транзакциях и уровнях их блокировок может идти речь?
При этом второй кассир ВООБЩЕ не должен иметь доступ на запись к этому заказу. Надеюсь, понимаете, почему.
Вот такая вот предметная область.
Если у Вас есть решение лучше, чем блокировка на запись с помощью доп. поля - готов выслушать


MsGuns   (2006-11-22 20:30:00) [96]

>DeadMeat ©   (22.11.06 16:25) [19]
>Проблему решил так:
>1. Обновление всего списка по таймеру или по кнопке в зависимости от настроек.

Не делайте этого !

>2. Обновление текущей записи прямо перед открытием ее для редактирования.

Это ничего Вам не даст в плане актуальности этой самой записи.


MsGuns   (2006-11-22 20:27:00) [97]

>clickmaker ©   (20.11.06 17:02) [2]
>Знакомая проблема, ага.
>Но решений, увы, кот наплакал.
(Дальше не привожу, ибо уже полный бред)

 +

>clickmaker ©   (21.11.06 09:59) [13]
>Ну как... юзер1 поменял что-то, нажал ОК. Запись закоммитилась, блокировку сняли. Теперь она доступна другим, уже с измененными данными.

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

Я извиняюсь перед Мастером, но все же задам 2 вопроса:

1) Вы знакомы с понятием "транзакции" и "взаимовлияние транзакций" ?
и
2) в какой это предметной области Вы городите всю эту чушь ?

ЗЫ. Обратите все же внимание на пост [9]


DeadMeat   (2006-11-22 16:25:00) [98]

Спасибо всем ответившим.
Проблему решил так:
1. Обновление всего списка по таймеру или по кнопке в зависимости от настроек.
2. Обновление текущей записи прямо перед открытием ее для редактирования.

Пункт 1 пришлось ввести из-за того, что пользователей не 2, а больше и изменять они могут сразу несколько записей (каждый свою), поэтому приходится обновлять весь список.
ИМХО, нужда в отдельном сервисе появится в том случае, если количество записей перевалит за предел, в результате которого время обновления увеличится секунд так до 5-6. И то, можно обойтись без этого используя подкачку. Обновлять только те записи, на которые сейчас смотрит пользователь. Думаю этого должно хватить...

Спасибо еще раз за советы... Вы мне очень помогли.

ЗЫ. После некоторых поисков по исходникам EhLib нашел тоже самое - обновление только одной записи. Поэтому пока что останусь на нем.


Bless   (2006-11-21 15:54:00) [99]


> ADODataSet1.Properties['Resync Command'].Value


q.Properties['Resync Command'].Valueконечно же


Bless   (2006-11-21 15:52:00) [100]


> Но вот как после обновления попросить сервер вернуть только
> одну эту измененную запись, а не весь набор целиком?
>


Как-то давно, на этом форуме давали пример:

var
 q:TCustomADODataset;

...
//обновить текущую запись датасета q
 q.UpdateCursorPos;
 q.Recordset.Resync(adAffectCurrent,adResyncAllValues);
 q.Resync([rmExact]);
...


Чтобы обновление работало, как ожидается, возможно, также понадобится настроить ADODataSet1.Properties['Resync Command'].Value


Страницы:   1 2 3 4 5 6

Наверх

Титульная страница Поиск, карта сайта Написать письмо