[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

ukb

10/12/2005 10:40:00 AM

I have a problem in the getNumInternal method in the NumberSeq class. As part
of a longer chain of events several records are to be inserted in the
InventJournalVoucher table. During an insertion the
NumberSeq.getNumInternal() is called:

protected Num getNumInternal(NumberSequenceCode _numberSequenceCode)
{
Num _num = '';
NumberSequenceTable numberSequenceTable;
UserConnection userConnection;
xApplication xApplication = new xApplication();
;
this.setGlobalTransId();

userConnection = new UserConnection();

userConnection.ttsbegin();

sequenceUpdated = FALSE;

numberSequenceTable.setConnection(userConnection);

select forUpdate firstOnly numberSequenceTable
index hint SeriesIdx
where numberSequenceTable.numberSequence == _numberSequenceCode;

(...)
}


Second time around the select statement causes the system to block as if the
previous userConnection hasn't finished or comitted properly.

There are two old threads regarding this issue, 9139.1 and 10958.1, but no
one has had any solutions.

if anyone has any ideas as to what might be causing this or a possible
solution I would really appreciate it!

By the way, I am running Axapta 2.5 Option pack 2.5.

Thanks
ukb

5 Answers

Micha³ Kupczyk

10/12/2005 1:39:00 PM

0

"ukb" wrote in message
>I have a problem in the getNumInternal method in the NumberSeq class. As
>part
> of a longer chain of events several records are to be inserted in the
> InventJournalVoucher table. During an insertion the
> NumberSeq.getNumInternal() is called:

> Second time around the select statement causes the system to block as if
> the
> previous userConnection hasn''t finished or comitted properly.
>
> There are two old threads regarding this issue, 9139.1 and 10958.1, but no
> one has had any solutions.
>
> if anyone has any ideas as to what might be causing this or a possible
> solution I would really appreciate it!
>

I do not have 2.5, but IMHO you can try to modify Application class, adding
support for registering / deregistering your connections to be aborted when
exception is thrown and control is going beyond ttsabort;

xApplication
classDeclaration
{
....
set connToBeAborted;
}
void registerConn(UserConnection _userConn)
{
if(!connToBeAborted.Exist(_userConn))
connToBeAborted.Add(_userConn)
}

void deregisterconn(_userconn)
{
connToBeAborted.Delete(_userConn)
}

void ttsNotifyAbort()
{
[original stuff here]
get all your still registered connections
{
setElement.Delete(); //destroy connection object, not
automaticly destroyed because reference was stored here.
eachUserConn.Abort();
}
map = NULL; // just for sure, to destroy all contained connections, that
were not destroyed because reference was stored HERE.
}


and in
NumberSeq.getNumInternal(...)
{
....
userConnection = new UserConnection();
appl.registerConn(userConnection);


if (!ok)
{
appl.deregisterConn(userConnection);
userConnection.ttsabort();
throw error("@SYS25038");
}
}


ttsNotifyAbort is called only for primary connection.
As a effect, all transactions in connections that you''ve lost control will
be at least aborted and maybe destroyed.

Michal



ukb

10/13/2005 10:31:00 AM

0

Hi Michal

Thank you very much for your quick response!

There is a little problem with your proposed solution, though. The first
time getNumInternal is run, it completes without problems and does ttscommit
on the userConnection.

The second time, when the select statement is reached, the system is
blocked. No deadlock or other exception is thrown, Axapta just freezes at the
select statement. I guess your solution only works if an exception is thrown.

Also, how can I modify the xApplication class? As a kernel class I can only
find it in the System Documentation node in the AOT, where there is no access
to the code?

Thanks
Ulrik

"Michal Kupczyk >" wrote:

> I do not have 2.5, but IMHO you can try to modify Application class, adding
> support for registering / deregistering your connections to be aborted when
> exception is thrown and control is going beyond ttsabort;
>
> xApplication
> classDeclaration
> {
> ....
> set connToBeAborted;
> }
> void registerConn(UserConnection _userConn)
> {
> if(!connToBeAborted.Exist(_userConn))
> connToBeAborted.Add(_userConn)
> }
>
> void deregisterconn(_userconn)
> {
> connToBeAborted.Delete(_userConn)
> }
>
> void ttsNotifyAbort()
> {
> [original stuff here]
> get all your still registered connections
> {
> setElement.Delete(); //destroy connection object, not
> automaticly destroyed because reference was stored here.
> eachUserConn.Abort();
> }
> map = NULL; // just for sure, to destroy all contained connections, that
> were not destroyed because reference was stored HERE.
> }
>
>
> and in
> NumberSeq.getNumInternal(...)
> {
> ....
> userConnection = new UserConnection();
> appl.registerConn(userConnection);
>
>
> if (!ok)
> {
> appl.deregisterConn(userConnection);
> userConnection.ttsabort();
> throw error("@SYS25038");
> }
> }
>
>
> ttsNotifyAbort is called only for primary connection.
> As a effect, all transactions in connections that you''ve lost control will
> be at least aborted and maybe destroyed.
>
> Michal
>
>
>
>

ukb

10/13/2005 10:52:00 AM

0

Hi Michal

Just forget about the "modify the xApplication class" part of my previous
question. You meant (and did write) of course the Application class which is
perfectly modifiable...

Thanks
Ulrik


Micha³ Kupczyk

10/13/2005 11:26:00 AM

0

Hi,
There is everything ok with the code. (on 3.0)
side question: Is standard 2.5 code designed to issue userConn.ttsbegin()
and userConn.ttsabort() ?
If code is correct, try to set breakpoint at the end of getNumInternal, and
see if rows are still locked. Assuming MSSQL, you can check it using
Enterprise Mgr.
If they are still locked, then the userConn.ttsCommit() (or
userConn.ttsAbort() ) does not work.
Try to recompile, and if still not ok, then change anything in this class
(move to usr layer ) and recompile.

For me one reason for those rows being still locked is the exception is
raised between conn.ttsbegin() and conn.ttscommit() and when
UserConnection goes out of scope it does not do ttsabort. Modification I
suggested tries to addres this case

Michal


ukb

1/2/2006 12:11:00 PM

0

Hi Michal

By using the method of checking in Enterprise Manager when the table locked
, I found out that the error occurred elsewhere in the system.

In the method Classes\NumberSeq.release() the NumberSequenceTable is
selected for update in a call to NumberSequenceTable::find. Under certain
circumstances the outermost ttscommit in a long line of method calls and
ttsbegin/ttscommit pairs wasn't reached and therefore this lock was never
released before executing getNumInternal() again.

Luckily, NumberSequenceTable is not updated in the release method so I could
bypass the problem by calling the find method with _forUpdate=false.

To answer your question, standard 2.5 does use userConnection.ttsbegin() and
userConnection.ttscommit().

Thank you very much for your help. It is much appreciated!

Thanks,
Ulrik


"Michal Kupczyk >" wrote:

> Hi,
> There is everything ok with the code. (on 3.0)
> side question: Is standard 2.5 code designed to issue userConn.ttsbegin()
> and userConn.ttsabort() ?
> If code is correct, try to set breakpoint at the end of getNumInternal, and
> see if rows are still locked. Assuming MSSQL, you can check it using
> Enterprise Mgr.
> If they are still locked, then the userConn.ttsCommit() (or
> userConn.ttsAbort() ) does not work.
> Try to recompile, and if still not ok, then change anything in this class
> (move to usr layer ) and recompile.
>
> For me one reason for those rows being still locked is the exception is
> raised between conn.ttsbegin() and conn.ttscommit() and when
> UserConnection goes out of scope it does not do ttsabort. Modification I
> suggested tries to addres this case
>
> Michal
>
>
>