Rambler's Top100
Форум: MS ACCESSVBVBA MS OfficeMS SQL server
Новые сообщения: 0000

Форум: MS ACCESS

Вопросы связанные с MS ACCESS

Обновить визитку
Участники «Online»
Все участники

 
 

Доброго времени суток, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Решение вопроса конкурентной записи при общемдоступе
 
 автор: luj   (17.09.2009 в 13:13)   личное сообщение
19 Кб.
 
 

Вот вопрос!
- Необходимо решение: для записи в одну базу (связные таблици) с двух или более компьютеров, записей с последовательной нумерацией.
Седлал такую хохму. Вроде работает. Кто подскажет более простой способ - РЕСПЕКТ.
Это Важно и нужно срочно.
P/S перешарил форум. не нашёл ничего подходящего. Видел ADO но не възжаю как прикрутить это ADO и какие библиотеки нужны, в общем не работает.
icq 57707376 мыло integracia@mail.kz

  Ответить  
 
 автор: kot_k_k   (17.09.2009 в 13:52)   личное сообщение
 
 

а в чем проблем, ведь при добавлении записи (обработка соответсвующего Собития формы) можно найти максимальный Номер и +1 к нему - занести в Номер.
Хоть 2 компа хоть 100.

- Событие До вставки (BeforeInsert) возникает при вводе пользователем первого символа в новую запись, но до фактического создания записи.
- Событие После вставки (AfterInsert) возникает после добавления новой записи.

Хоть круть-верть хоть верть-круть

  Ответить  
 
 автор: luj   (17.09.2009 в 14:56)   личное сообщение
 
 

СПАСИБО! думал не дождусь!
Согласен.
тут немного другая ситуация. добавление записей интерактивное, после сбора набора-записей по таблицам через recordset и потом инсерт в таблицу и обновление набора записей формы.
полагаю что можнго сделать прямой form.recordsourse и работа с ним. но так. как в этом recordsourse набор разных данных так же с встроенными запросами то добавить запись(стандартный способ docmd.gotoRecord acNew не прет.) можно только через рекордсет для главной таблицы в этом наборе записей через Insert и потом сделать для формы Requery. вот ут то и рекордсет прежде чем добавить смотрит занята таблица или нет и вслучае если она свободна делает свое дело :) но как еще это можно стандартно сделать? для RecordSet. в предложенном мной варианте не могу перехватить ошибку run-time которая возникает только во время выполнения вслучае если таблицу захватил другой рекордсет и вызвал .Edit или .AddNew если бы смог то и код был бы смешным и простым. а тут скажем так наворотил от не знания.
ИЛИ Я ЧЕГО НЕ ПоНиМаЮ. МАЛЕНЬКИЙ ПРИМЕР В СТУДИЮ :) ПЛЗ.

  Ответить  
 
 автор: kot_k_k   (17.09.2009 в 15:19)   личное сообщение
 
 

Вопрос пользователь заносит данные в таблу напрямую?
если да то не очень правильно.
я всегда делаю форму ввода в таблу ТМР_Таблица
по кнопке "Сохранить" провожу обновление Таблицы на основании ТМР_Таблицы программно и если так сделать в этом случае то вероятность сбоя невероятна.

и еще написал письмо на мыло пришел ответ с эл.адресом страницы и две строчки знак вопроса - перепробовал кодировки не помогло

  Ответить  
 
 автор: Анатолий (Киев)   (17.09.2009 в 14:46)   личное сообщение
 
 

Что бы что-то подсказать, надо сначала понять, что вы хотите.
Какой тайный смысл в этой проверке?

If res.Transactions = False Then

Здесь вы добавляете к значению таймера от 0(!) до 9 секунд. Почему не конкретное значение?

a = Timer + Mid(Timer, 4, 1)


После того, как вы "быстренько" внесли 1501 номеров, каждый следующий добавляется раз в минуту. Смысл?

Какой смысл в обнулении поля, если процедура продолжается и ему тут же подставляется следующее значение счетчика.

If Me.TimerInterval = 60000 Then
Me.№_заказа = 0
End Ifd If 

  Ответить  
 
 автор: luj   (17.09.2009 в 15:05)   личное сообщение
 
 

If res.Transactions = False Then
проверяет не открыта ли запись для изменения. в таблице , в которой регистрируется последний использовавшийся номер.
т.е. ведется таблица. а рекордсер для получения номера отправляется в другую таблицу, которая имеет всего одну запись. там все рекордсеты берут свободный номер и отмечабт его занятым. т.е. т.к там всегь одна запись то рекордсеты идут на +. и после получения номера добавляет запись в общую таблицу записей с правильным номером.
кстати вот всетаки на 10000 записей встречался один глюк. таблица открыта и другой пользователь не может выполнить.Update вся эта канитель висла наглухо. Тут как раз бы использовать перехват run-time для рекордсетов. КАК не знаю :-(

a = Timer + Mid(Timer, 4, 1)

тут для уверености. рекордсет освобождает таблицу но реально она освобождается в течении 2-3 секунд. для захвата другим пользователем. тут ГСЧ.

If Me.TimerInterval = 60000 Then
Me.№_заказа = 0
End Ifd If
эти формы сделаны для проверки на наличие глюков. реально же все будет работать то нажатию клавиши. т.е. ак максимум 1 раз в 30 секунд (зависит от скорости набора диспетчера :-) )
так вот это один из моментов старого кода (забыл выкинуть) точка останова для выхода из процедуры при тестировании.
Я запускал с разных баз две формы с одинаковым кодом (таблици были прилинкованы из независимой БД) и проверял как это все отработает

  Ответить  
 
 автор: Анатолий (Киев)   (17.09.2009 в 16:34)   личное сообщение
 
 

Св-во Transactions служит для проверки, допускается ли использование транзакций. Зависит от тапа рекордсета и никак не зависит от того, занята ли таблица другим юзером. Или у вас бывает False?
Я бы открывал rst1 c опцией dbDenyRead при включенном On Error Resume Next. Если таблица редактируется другим юзером - возникает ошибка, которую надо сбросить и после паузы повторить попытку (в цикле, пока таблица не освободится).
С rst2 можно dbDenyRead не применять, но вместо dbOptimistic (как у вас) применить dbPessimistic (и логично с dbAppendOnly). Тогда ошибка будет возникать на .AddNew. Ее тоже надо сбросить и после паузы повторить попытку.

Для выполнения паузы удобно использовать API:
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

  Ответить  
 
 автор: luj   (17.09.2009 в 16:48)   личное сообщение
 
 

ОК! СПАСИБО БОЛЬШОЕ!!!
сейчас испытаю :)
Да бывает =false проверьте код сделайте точку останова на !№_заказа = * в одной форме и потом проверьте в другой свойства transaction

  Ответить  
 
 автор: Анатолий (Киев)   (17.09.2009 в 18:08)   личное сообщение
 
 


Да бывает =false проверьте код сделайте точку останова на !№_заказа = * в одной форме и потом проверьте в другой свойства transaction


Когда программа до точки останова, то останавливается ВСЁ, в т.ч. и выполнение в другой форме. Даже не знаю, как вы смогли это проверить.
Запустил два экземпляра БД - False не увидел.

Запустил такую процедуру, получаю оба True:

    Set res = CurrentDb.OpenRecordset("ZakN", , , 3)
    Set res2 = CurrentDb.OpenRecordset("ZakN", , , 3)
    res.Edit
    res("№_заказа") = 1
    
    MsgBox res.Transactions & vbCrLf & res2.Transactions

  Ответить  
 
 автор: luj   (17.09.2009 в 18:57)   личное сообщение
 
 

все, я понял. видимо когда одна форма вылетала по рунтайм, тоесть код был еще недоделан для работы с этой ошибкой. тогда то я и получал значение фальсе иначе объяснить не могу :)

  Ответить  
 
 автор: luj   (17.09.2009 в 19:01)   личное сообщение
41 Кб.
 
 

вот она :) с картинкой как тестировал - 4 формы в разных базах, таймер 300 , колво значений 10500, формы остановились со значениями от 10501 до 10504 ни одной ошибки

ОГРОМНОЕ СПАСИБО - - - - - - ДЛЯ Анатолий (Киев)


Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Private Sub Form_Timer()
Dim res As Recordset, res2 As Recordset, a As Long


a = 0
Me.two = 0

restart:

err.Clear

On Error Resume Next

Sleep (a)

Set res = CurrentDb.OpenRecordset("ZakN", , dbDenyRead, 2) 'dbDenyRead


Me.two = Me.two + 1
Me.Repaint

With res

If res.RecordCount = 0 Then
.AddNew
res("№_заказа") = 1
Else
.Edit
res("№_заказа") = IIf(res("№_заказа") = "" Or IsNull(res("№_заказа")), 1, res("№_заказа") + 1)
End If
Me.one.Value = res("№_заказа")
.Update

End With

a = Mid(Timer, 6, 3)
If err.number <> 0 Then Resume restart

res.Close

a = 0

restart1:

err.Clear

On Error Resume Next

Sleep (a)

Set res2 = CurrentDb.OpenRecordset("TF_ADDress", , dbAppendOnly, 2)

With res2

.AddNew
!аддрес = Me.one
.Update

End With


a = Mid(Timer, 6, 3)
If err.number <> 0 Then Resume restart1

res2.Close

If Me.one > 10500 Then Me.TimerInterval = 0

End Sub

  Ответить  
 
 автор: luj   (25.10.2009 в 21:41)   личное сообщение
 
 

в этом коде еще нужно добавить перехват конкретной ошибки которая вас интересует и поставить метку возврата перед .UPDATE иначе добавляет несколько раз :)

  Ответить  
 
 автор: П.Полиграфович   (27.10.2009 в 01:55)   личное сообщение
 
 

Или без API попробовать с таймером поиграть в 3-5 секунды ..))

  Ответить  
HiProg.com - Технологии программирования
Rambler's Top100 TopList