AX TTS总结

AX的事物管理通过关键字ttsbegin/ttscommit/ttsabort来处理用一个事务要不全做要不全不做

常用的写法有:

 1 try
 2 {
 3   ttsbegin;
 4   //do something1
 5   //do something2
 6   ttscommit;
 7 }
 8 catch
 9 {
10   ttsabort;
11 }

这里do something1do something2,要不全做其中有一个出现问题,则两个都不做

另外使用tts,还有下面一些小细节:

(1)ttsabort不会马上终止程序,而是继续运行后面与transaction无关的statements (best practise建议使用throw exception而取代ttsabort)。

(2)嵌套tts,直到最外层的ttscommit运行后,数据才真正更新到数据库中。

(3)系统内置有一个叫ttslevel的变量,默认是0。每次ttsbegin,ttslevel就加1,每次ttscommit,ttslevel就减1,而ttsabort会直接把ttslevel清0。也就是0这个状态才代表整个transaction运行完事。当使用ax的form保存数据的时候,系统会首先检测ttslevel(比validateWrite更早,在form的task的super里头运行),如果ttslevel不为0,就会提示以下错误,导致更新终止。

(我们可以使用new xApplication().ttslevel()来查看当前的ttslevel)

看些例子:

例1

1           //Default at the beginning TTSLEVEL = 0                                                          
2 TTSBEGIN;       //TTSLEVEL = 1                                               
3 //Do something
4 TTSBEGIN;       //TTSLEVEL = 2
5 //Do something
6 TTSCOMMIT;       //TTSLEVEL = 1
7 //Do something
8 TTSCOMMIT;        //TTSLEVEL = 0.                                             

 

例2

 1                //Default at the beginningTTSLEVEL = 0
 2 TTSBEGIN;          //TTSLEVEL = 1
 3 //Do something
 4 try
 5 {
 6   TTSBEGIN;        //TTSLEVEL = 2
 7    //Do something
 8    TTSCOMMIT;             //TTSLEVEL = 1 (没错误情况)
 9 }
10 catch
11 {
12   TTSABORT;             //TTSLEVEL = 0 (有错误情况)
13     //Do something
14 }
15 TTSCOMMIT;               //TTSLEVEL = 0 (没错误情况),
16                //TTSLEVEL = -1 (有错误情况), 这个绝对不是我们想要得到的结果.所以结合第一点,我们应尽量避免使用ttsabort

(4)ttsbeginttscommit中间的程序在最外层ttscommit之前是不会更新数据库的但如果通过AX代码更新数据在没有commit之前依然能获取transaction前半段插入的数据

试试下面例子:

 1 static void testTTS(Args _args)
 2 {
 3   VendTable vendTable, vendTable2;
 4   ;
 5 
 6   ttsbegin;
 7   vendTable.clear();
 8   vendTable.AccountNum = 'TestingTTS';
 9   vendTable.doInsert();
10   select vendTable2
11     where vendTable2.AccountNum == 'TestingTTS';
12 
13   print vendTable2.AccountNum;
14   //取得记录
15 
16   vendTable2 = VendTable::find('TestingTTS');
17 
18   print vendTable2.AccountNum;
19   //取得记录
20 
21   pause;
22 
23   delete_from vendTable
24     where vendTable.AccountNum == 'TestingTTS';
25   ttscommit;
26 }

所以我们有理由怀疑AX会合并内存和数据库中的内容,便于我们编程。但是如果通过外部程序直接查询数据库,那在commit之前是不能读出那些在transaction中途插入或修改的数据的(有个具体例子是,我们使用Table来保存一些打印数据,然后调用外部水晶报表程序来打印报表。该水晶报表直接读取AX数据库,所以他打印报表那句必须在commit之后调用,否则不能读出相应数据)

(5)ttsbegin/ttscommit/ttsabort针对写入数据库的事务管理。那么对于只更新内存的临时表的写入,它们是不起作用的。对于临时表,我们需要使用

  临时表变量.ttsbegin();

  临时表变量.ttscommit();

  临时表变量.ttsabort();

(6)update_recordset,delete_from,insert_recordset那些语句是单条SQL命令,无需事务控制。

 

  感谢秋毫的fat0527总结。

 

 

posted @ 2012-08-27 17:04  Sprite.z  Views(753)  Comments(0Edit  收藏  举报