Цитата |
---|
nordk пишет:
При такой конструкции в сети на 10 пользователей Вы точно совершенно две одинаковые записи не получите.
Мы говорим о механизме записи: я не проверял точность индексного ключа и т.п. |
Ну, чтож, давайте проверим. (Хотя при чем тут индекс).
Для этого возьмем функцию, создающую Н\Н с заполнением нескольких полей. Ту, которую рассмотрели ранее:
Код |
---|
STATIC PROCEDURE CreateNewProduct()
Local sNewNNumReal:=Space(13)
SET ORDER TO TAG TAG_NNum
DbGoBottom()
sNewNNumReal:=mlabel->nnum
if(sNewNNumReal==AllTrim(sNewNNumReal))
if(.NOT.(IfAllChar(sNewNNumReal)))
WHILE Mlabel->(DBSEEK(UPPER(" "+sNewNNumReal)))
sNewNNumReal:=InCreaseOne(MLABEL->NNUM)
ENDDO
Mlabel->(ADDREC())
Mlabel->NNUM:=sNewNNumReal
Mlabel->GRUP:="00001"
Mlabel->NAME:="Новая"
Mlabel->FULLNAME:="Новая полное"
Mlabel->ORD_POLICY:=1
Mlabel->ID_LABEL:=StepPlus()
Mlabel->mdim:="0000000000000000001040"
Mlabel->( F_DBUNLOCK() )
endif
endif
return |
Функции, которая использует ф-я создани ном-ры приведу ниже.
Теперь, используем эту функции в нашей спецфункции:
Код |
---|
StartTest()
STATIC PROCEDURE StartTest()
Local Temp_I:=0
Local dStart,dEnd
dBpUSH()
dStart:=Time()
If (DbF()=="MLABEL")
For Temp_i:=1 to 20000
CreateNewProduct()
NEXT
ENDIF
dEnd:=TIME()
SayAndWait("Время старта "+Var2Char(dStart)+" время окончания"+Var2Char(dEnd))
DbPop()
RETURN |
Будет выводиться время начала и время окончания работы спецф-ии.
Подготовим справ номенклатуры. Для этого удалим там все записи, создадим запись под номером "0000000000001"(Этого изначально требует работа со справочником) в группе "00001". У нас запущено одно окно.
1. Запускаем спецфункцию. (Создадим 20к записей для "веса").
2. Запускаем 2е окно и как можно быстрее запускаем в обоих окнах спецфункцию.
Результат записываем. Вот что получилось у меня(МИН:СЕК):
1.10:50 - 11:08. Dbf Viewer показывает 20001 запись. Н\Н Последней 20001.
2. 1е окно: 13:23 - 13:59
2е окно: 13:24 - 14:00
Результат: Dbf Viewer показывает 60001 запись. Н\Н Последней 42276.
Проведем 2й раз опыт (подгтовка справочника, реиндексация).
1.33:07 - 33:21. Dbf Viewer показывает 20001 запись. Н\Н Последней 20001.
2. 1е окно: 34:20 - 34:57
2е окно: 34:21 - 34:58
Результат: Dbf Viewer показывает 60001 запись. Н\Н Последней 42103.
Результат, в общем-то плачевный. Получилось, что около 18000 записей дублируют номера. (Хотя один раз получился результат с дубляжом порядка 500 записей, там был немного др алгоритм, но принцип проверки тот же.).
Теперь рассмотрим причину, по которой такое происходит. Обратимся к куску кода:
Цитата |
---|
WHILE Mlabel->(DBSEEK(UPPER(" "+sNewNNumReal)))
sNewNNumReal:=InCreaseOne(MLABEL->NNUM)
ENDDO
Mlabel->(ADDREC())
Mlabel->NNUM:=sNewNNumReal
Mlabel->GRUP:="00001"
Mlabel->NAME:="Новая"
Mlabel->FULLNAME:="Новая полное"
Mlabel->ORD_POLICY:=1
Mlabel->ID_LABEL:=StepPlus()
Mlabel->mdim:="0000000000000000001040"
Mlabel->( F_DBUNLOCK() )
|
Жирным выделением отметил место где начинается "критический" код и где он заканчивается. Если разделить эти участки кода от одновременного исполнения - то никаких ошибок не будет. Как это сделать сейчас?
Естественно "заморозить" процесс я не могу. Однако, можно поступить по-идиотски, а именно разделить его так:
Цитата |
---|
Do While (.NOT.(lUnique).AND.(nJ<1000))
TRY
USE (sPath) NEW Alias TEmp
lUnique:=.T.
SELECT ("MLABEL")
SET ORDER TO TAG TAG_NNum
CATCH oErr
nJ+=1
end
enddo//правильнее еще сделать проверку на велич счетчика.
WHILE Mlabel->(DBSEEK(UPPER(" "+sNewNNumReal)))
sNewNNumReal:=InCreaseOne(MLABEL->NNUM)
ENDDO
Mlabel->(ADDREC())
Mlabel->NNUM:=sNewNNumReal
Mlabel->GRUP:="00001"
Mlabel->NAME:="Новая"
Mlabel->FULLNAME:="Новая полное"
Mlabel->ORD_POLICY:=1
Mlabel->ID_LABEL:=StepPlus()
Mlabel->mdim:="0000000000000000001040"
Mlabel->( F_DBUNLOCK() )
Close Temp
|
Имея такой инструмент, можно было бы вообще отказаться от проверки и переделать алгоритм, но посмотрим что получиться при таком коде.
Результаты:
1. 14:21 - 14:39. Записей 20001, Н\Н последней 20001. Все верно.
2. 1е окно 15:28 - 16:27
2е окно 15:29 - 16:28
Результат: Записей - 60001, номер последней записи 60001. А это значит, что не допущено ни единой ошибки!!!!
Код |
---|
Function IncreaseOne(cString)
Local nLength:=0
Local cIncreased:=""
Local nPosition:=0 //Цифра - разряд
nLength:=len(cString)
cIncreased:=stuff(cString,1,nLength-1,"")
If(IsDigit(cIncreased))
nPosition:=Val(cIncreased)
if(nPosition==9)
if(nLength==1)
cIncreased:=""// нужен сЛУЧАЙНЫЙ СИМВОЛ
else
nPosition:=0
cIncreased:=IncreaseOne(stuff(cString,nLength,nLength,""))
if(.NOT.(cIncreased==""))
cString:=cIncreased+Var2Char(nPosition)
else
cString:=""
endif
endif
else
nPosition+=1
cString:=stuff(cString,nLength,nLength,Var2Char(nPosition))
endif
else
nPosition:=0
cIncreased:=IncreaseOne(stuff(cString,nLength,nLength,""))
if(.NOT.(cIncreased==""))
cString:=cIncreased+Var2Char(nPosition)
else
cString:=""
endif
endif
return cString
Function IfAllChar(cString)
Local bIfNotNumExist:=.T.
Local nLen:=len(cString),temp_i:=0,temp_j:=0
if (nLen!=0)
While(bIfNotNumExist)
if(IsDigit(cString))
bIfNotNumExist:=.F.
else
cString:=Stuff(cString,1,1,"")
endif
enddo
endif
return bIfNotNumExist
//Измененная ф-я создания:
STATIC PROCEDURE CreateNewProduct()
Local sNewNNumReal:=Space(13)
Local lUnique:=.F.
Local nJ:=1,oErr
Local sPath:=LoadPath()+"TEST\BOM_def"
SET ORDER TO TAG TAG_NNum
DbGoBottom()
sNewNNumReal:=mlabel->nnum
if(sNewNNumReal==AllTrim(sNewNNumReal))
if(.NOT.(IfAllChar(sNewNNumReal)))
Do While (.NOT.(lUnique).AND.(nJ<1000))
TRY
USE (sPath) NEW Alias TEmp
lUnique:=.T.
SELECT ("MLABEL")
SET ORDER TO TAG TAG_NNum
CATCH oErr
nJ+=1
end
enddo
WHILE Mlabel->(DBSEEK(UPPER(" "+sNewNNumReal)))
sNewNNumReal:=InCreaseOne(MLABEL->NNUM)
ENDDO
Mlabel->(ADDREC())
Mlabel->NNUM:=sNewNNumReal
Mlabel->GRUP:="00001"
Mlabel->NAME:="Новая"
Mlabel->FULLNAME:="Новая полное"
Mlabel->ORD_POLICY:=1
Mlabel->ID_LABEL:=StepPlus()
Mlabel->mdim:="0000000000000000001040"
Mlabel->( F_DBUNLOCK() )
Close Temp
endif
endif
return
//В качестве "Блокирующего" файла
//взял BOM_def, он у нас все
//равно пуст. Файл обязательно
// должен присутствовать в папке TEST!!!!!!
|