Inside Dynamics Axapta源代码赏析(五)
第十二章 The Database layer
1.更改RecVersion
AX4.0使用了乐观并发控制,RecVersion是用来标识记录版本的。
2.跳过ForUpdate和TTSbegin,TTSCommit的检查.
3.临时表的使用.
通过setTmp和data两个方法可以搞定.
1.更改RecVersion
AX4.0使用了乐观并发控制,RecVersion是用来标识记录版本的。
static void RecVersionChange(Args _args)
{
CustTable custTableSelected;
CustTable custTableSelectedForUpdate;
CustTable custTableUpdated;
;
ttsbegin;
select custTableSelected
where custTableSelected.AccountNum == '4000';
select forupdate custTableSelectedForUpdate
where custTableSelectedForUpdate.AccountNum == '4000';
select forupdate custTableUpdated
where custTableUpdated.AccountNum == '4000';
// At this point, RecVersion in all three buffers are equal.
custTableUpdated.CreditMax = custTableUpdated.CreditMax;
custTableUpdated.update();
print custTableUpdated.recVersion;
print custTableSelectedForupdate.recVersion;
print custTableSelected.recVersion;
// At this point, RecVersion is changed in the custTableUpdated
// and custTableSelectedForUpdate buffers. CustTableSelected still
// has its original value in RecVersion.
ttscommit;
pause;
}
{
CustTable custTableSelected;
CustTable custTableSelectedForUpdate;
CustTable custTableUpdated;
;
ttsbegin;
select custTableSelected
where custTableSelected.AccountNum == '4000';
select forupdate custTableSelectedForUpdate
where custTableSelectedForUpdate.AccountNum == '4000';
select forupdate custTableUpdated
where custTableUpdated.AccountNum == '4000';
// At this point, RecVersion in all three buffers are equal.
custTableUpdated.CreditMax = custTableUpdated.CreditMax;
custTableUpdated.update();
print custTableUpdated.recVersion;
print custTableSelectedForupdate.recVersion;
print custTableSelected.recVersion;
// At this point, RecVersion is changed in the custTableUpdated
// and custTableSelectedForUpdate buffers. CustTableSelected still
// has its original value in RecVersion.
ttscommit;
pause;
}
2.跳过ForUpdate和TTSbegin,TTSCommit的检查.
CustTable custTable;
;
ttsbegin;
select custTable where custTable.AccountNum == '4000';
custTable.CreditMax = 1000;
custTable.skipTTSCheck(true);
custTable.update();
ttscommit;
这样是可以跳过,但为什么要跳过那?;
ttsbegin;
select custTable where custTable.AccountNum == '4000';
custTable.CreditMax = 1000;
custTable.skipTTSCheck(true);
custTable.update();
ttscommit;
3.临时表的使用.
通过setTmp和data两个方法可以搞定.
static void TmpCustTable(Args _args)
{
CustTable custTable;
CustTable custTableTmp;
;
custTableTmp.setTmp();
ttsbegin;
while select custTable
{
custTableTmp.data(custTable);
custTableTmp.doInsert();
}
ttscommit;
}
{
CustTable custTable;
CustTable custTableTmp;
;
custTableTmp.setTmp();
ttsbegin;
while select custTable
{
custTableTmp.data(custTable);
custTableTmp.doInsert();
}
ttscommit;
}
Table有两个方法,data()和setTmpData(),其中Data()是拷贝一份数据,而setTmpData()只是对象引用的传递.
4.临时表的清空
把临时表赋值为null的时候,内存被清空,临时文件被删除
static void TmpLedgerTable(Args _args)
{
TmpLedgerTable tmpLedgerTable;
;
tmpLedgerTable.CompanyId = 'dat';
tmpledgerTable.AccountNum = '1000';
tmpLedgerTable.AccountName = 'Name';
tmpLedgerTable.insert(); // Insert into first dataset.
tmpLedgerTable = null; // Allocated memory is freed
// and file is deleted.
tmpLedgerTable.CompanyId = 'dat';
tmpledgerTable.AccountNum = '1000';
tmpLedgerTable.AccountName = 'Name';
tmpLedgerTable.insert(); // Insert into new dataset.
//Check it
while select * from tmpLedgerTable
{
print tmpLedgerTable.AccountName;
}
pause;
}
{
TmpLedgerTable tmpLedgerTable;
;
tmpLedgerTable.CompanyId = 'dat';
tmpledgerTable.AccountNum = '1000';
tmpLedgerTable.AccountName = 'Name';
tmpLedgerTable.insert(); // Insert into first dataset.
tmpLedgerTable = null; // Allocated memory is freed
// and file is deleted.
tmpLedgerTable.CompanyId = 'dat';
tmpledgerTable.AccountNum = '1000';
tmpLedgerTable.AccountName = 'Name';
tmpLedgerTable.insert(); // Insert into new dataset.
//Check it
while select * from tmpLedgerTable
{
print tmpLedgerTable.AccountName;
}
pause;
}
5.下面的这段代码正好印证了前面的说法,setTmpData是指向同一个对象的.
static void TmpLedgerTable(Args _args)
{
TmpLedgerTable tmpLedgerTable1;
TmpLedgerTable tmpLedgerTable2;
;
tmpLedgerTable2.setTmpData(tmpLedgerTable1);
tmpLedgerTable1.CompanyId = 'dat';
tmpledgerTable1.AccountNum = '1000';
tmpLedgerTable1.AccountName = 'Name';
tmpLedgerTable1.insert(); // Insert into shared dataset.
tmpLedgerTable2.CompanyId = 'dat';
tmpledgerTable2.AccountNum = '1000';
tmpLedgerTable2.AccountName = 'Name';
tmpLedgerTable2.insert(); // Insert will fail with dublicate value.
}
{
TmpLedgerTable tmpLedgerTable1;
TmpLedgerTable tmpLedgerTable2;
;
tmpLedgerTable2.setTmpData(tmpLedgerTable1);
tmpLedgerTable1.CompanyId = 'dat';
tmpledgerTable1.AccountNum = '1000';
tmpLedgerTable1.AccountName = 'Name';
tmpLedgerTable1.insert(); // Insert into shared dataset.
tmpLedgerTable2.CompanyId = 'dat';
tmpledgerTable2.AccountNum = '1000';
tmpLedgerTable2.AccountName = 'Name';
tmpLedgerTable2.insert(); // Insert will fail with dublicate value.
}
6.ttsabort用于忽略记录的更改或插入.
剩下的代码都是一些关于事务和锁的问题,跟数据库的理论类似,这里就不摘录了.