Источник:
http://ax-som.blogspot.com/2008/01/n...unec-lock.html
==============
While working in multi user environment, if you are creating journal/journal line through code then you might the have the number sequence locking problem. For understanding the problem you can use following code
X++:
static void checkNumberSeq(Args _args)
{
NumberSeq numberSeq;
Voucher releaseVoucher;
;
ttsbegin;
numberSeq = NumberSeq::newGetVoucher(VendParameters::numRefVendPaymentVoucher());
releaseVoucher = numberSeq.voucher();
NumberSeq::release(VendParameters::numRefVendPaymentVoucher().NumberSequence,releaseVoucher);
//ttscommit;
//ttsbegin;
numberSeq = NumberSeq::newGetVoucher(VendParameters::numRefVendPaymentVoucher());
releaseVoucher = numberSeq.voucher();
ttscommit;
}
If you uncomment ttscommit/ttsbegin in the middle of this job first, it will work fine. If you comment them and run the job again, one NumberSequenceTable record gets locked, and the system hangs during second newGetVoucher() call.
This happens because standard Ax use pessimistic lock while generating new number.
To resolve this problem either you have to use newGetVoucher() out of ttsbegin/ttscommit scope.
Another way to resolve it (not thoroughly tested) is to modify method \Classes\NumberSeq\release as follows:
X++:
public static boolean release(NumberSequenceCode _numberSequenceCode,
Num _num
//#N, 1001 10/01/2008- -->
,userConnection userConnection = null
//#N, 1001 10/01/2008-
//numberSequenceTable = NumberSequenceTable::find(_numberSequenceCode,true);
if (prmIsDefault(userConnection))
{
userConnection = New userConnection();
}
userConnection.ttsbegin();
numberSequenceTable.setConnection(userConnection);
numberSequenceList.setConnection(userConnection);
select forUpdate firstOnly numberSequenceTable
index hint SeriesIdx
where numberSequenceTable.numberSequence == _numberSequenceCode;
//#N, 1001 10/01/2008-
userConnection.ttsabort();
//#N, 1001 10/01/2008- >--
throw error(strFmt("@SYS26271",_numberSequenceCode));
}
if (!numberSequenceTable.checkBlocked())
{
//#N, 1001 10/01/2008- -->
userConnection.ttsabort();
//#N, 1001 10/01/2008- >--
throw error("@SYS18447");
}
if (numberSequenceTable.continuous == NoYes::No)
ok = TRUE;
else
{
select forupdate firstonly numberSequenceList
index hint StatIdx
where numberSequenceList.numberSequence == _numberSequenceCode &&
numberSequenceList.num == _num;
if (numberSequenceList)
{
if (numberSequenceList.status == NumStatus::Free)
{
ok = TRUE;
}
else if (numberSequenceList.status == NumStatus::Active || numberSequenceList.status == NumStatus::Reserved)
{
if (numberSequenceList.transId)
{
numberSequenceList.status = NumStatus::Free;
numberSequenceList.transId = 0;
numberSequenceList.update();
select forupdate firstonly numberSequenceTTS
index hint TransIdIdx
where numberSequenceTTS.transId == numberSequenceList.transId;
if (numberSequenceTTS)
numberSequenceTTS.delete();
ok = TRUE;
}
else
{
xSession = new xSession(sessionId());
if (numberSequenceList.sessionId == xSession.masterSessionId() ? xSession.masterSessionId() : sessionId() &&
numberSequenceList.sessionLoginDate == xSession.loginDate() &&
numberSequenceList.sessionLoginTime == xSession.loginTime())
{
numberSequenceList.status = NumStatus::Free;
numberSequenceList.update();
ok = TRUE;
}
else
{
if (NumberSeqCleanUp::isProcessDead(numberSequenceList))
{
numberSequenceList.status = NumStatus::Free;
numberSequenceList.update();
ok = TRUE;
}
else
{
ok = FALSE;
}
}
}
}
}
else
{
numberSequenceList.numberSequence = _numberSequenceCode;
numberSequenceList.transId = 0;
numberSequenceList.status = NumStatus::Free;
numberSequenceList.num = _num;
numberSequenceList.insert();
ok = TRUE;
}
}
//#N, 1001 10/01/2008- -->
userConnection.ttscommit();
//#N, 1001 10/01/2008- >--
ttscommit;
return ok;
}
Источник:
http://ax-som.blogspot.com/2008/01/n...unec-lock.html