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++ code with posting jounral
----------------------------------------------------------
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++ code
-----------------------------------------------------------------------------------------------
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;
}
-------------------------------------------------------------------------------------------
没有评论:
发表评论