update_recordset降级的问题
<<Microsoft Inside Dynamics AX4.0>>的第十七章中在介绍批操作符update_recordset时提到在几种情况下可能会导致update_recordset降级,变成逐条更新,降级后的update_recordset会按照while select语句的处理方式完成更新,并举了如下例子:
static void UpdateSizes(Args _args)
{
InventSize inventSize;
;
ttsbegin;
update_recordset inventSize
setting description = 'This size is for item PB-Metal Shade'
where inventSize.ItemId == 'PB-Metal Shade';
ttscommit;
}
由于表InventSize没有满足使update_recordset降级的任何一个条件,所以上述语句在执行的时候将执行批处理操作,执行的SQL语句如下:{
InventSize inventSize;
;
ttsbegin;
update_recordset inventSize
setting description = 'This size is for item PB-Metal Shade'
where inventSize.ItemId == 'PB-Metal Shade';
ttscommit;
}
版本: Microsoft Dynamics 4.0 (内部版本号 2163)
数据库: Microsoft SQL Server
SQL 语句: UPDATE INVENTSIZE SET DESCRIPTION=?,RECVERSION=? WHERE ((DATAAREAID=?) AND (ITEMID=?)) [ID=386, 已重用=否]
这没有任何问题,inventsize中相应产品的描述信息被更改。数据库: Microsoft SQL Server
SQL 语句: UPDATE INVENTSIZE SET DESCRIPTION=?,RECVERSION=? WHERE ((DATAAREAID=?) AND (ITEMID=?)) [ID=386, 已重用=否]
我们让该表满足使update_recordset降级的一个条件,比如重载一下update方法,然后更改一下UpdateSizes方法中的description的值(因为如果本次更新的值跟原表中相应记录的值一样,while select只执行select语句,并不会执行更新语句)
static void UpdateSizes(Args _args)
{
InventSize inventSize;
;
ttsbegin;
update_recordset inventSize
setting description = 'update_recordset test'
where inventSize.ItemId == 'PB-Metal Shade';
ttscommit;
}
理论上应该降级成while select 语句完成更新,可是实际上并没有执行更新操作,查看执行的SQL语句,只有一条select语句{
InventSize inventSize;
;
ttsbegin;
update_recordset inventSize
setting description = 'update_recordset test'
where inventSize.ItemId == 'PB-Metal Shade';
ttscommit;
}
版本: Microsoft Dynamics 4.0 (内部版本号 2163)
数据库: Microsoft SQL Server
SQL 语句: SELECT A.INVENTSIZEID,A.ITEMID,A.NAME,A.RECVERSION,A.RECID,A.DESCRIPTION FROM INVENTSIZE A WITH( INDEX(I_1616ITEMSIZEIDX)) WHERE ((DATAAREAID=?) AND (ITEMID=?)) [ID=360, 已重用=是]
这个蛮让人费解,把上述语句改成while select语句:数据库: Microsoft SQL Server
SQL 语句: SELECT A.INVENTSIZEID,A.ITEMID,A.NAME,A.RECVERSION,A.RECID,A.DESCRIPTION FROM INVENTSIZE A WITH( INDEX(I_1616ITEMSIZEIDX)) WHERE ((DATAAREAID=?) AND (ITEMID=?)) [ID=360, 已重用=是]
static void UpdateSizes(Args _args)
{
InventSize inventSize;
;
ttsbegin;
while select forupdate inventSize
where inventSize.ItemId == 'PB-Metal Shade'
{
inventSize.Description = 'update_recordset test';
inventSize.update();
}
ttscommit;
}
执行了两条SQL语句:{
InventSize inventSize;
;
ttsbegin;
while select forupdate inventSize
where inventSize.ItemId == 'PB-Metal Shade'
{
inventSize.Description = 'update_recordset test';
inventSize.update();
}
ttscommit;
}
数据库: Microsoft SQL Server
SQL 语句: SELECT A.INVENTSIZEID,A.ITEMID,A.NAME,A.RECVERSION,A.RECID,A.DESCRIPTION FROM INVENTSIZE A WITH( INDEX(I_1616ITEMSIZEIDX)) WHERE ((DATAAREAID=?) AND (ITEMID=?)) [ID=10, 已重用=否]
SQL 语句: SELECT A.INVENTSIZEID,A.ITEMID,A.NAME,A.RECVERSION,A.RECID,A.DESCRIPTION FROM INVENTSIZE A WITH( INDEX(I_1616ITEMSIZEIDX)) WHERE ((DATAAREAID=?) AND (ITEMID=?)) [ID=10, 已重用=否]
版本: Microsoft Dynamics 4.0 (内部版本号 2163)
数据库: Microsoft SQL Server
SQL 语句: UPDATE INVENTSIZE SET DESCRIPTION=?,RECVERSION=? WHERE ((((DATAAREAID=?) AND (ITEMID=?)) AND (INVENTSIZEID=?)) AND (RECVERSION=?)) [ID=11, 已重用=否]
可以正常更新.数据库: Microsoft SQL Server
SQL 语句: UPDATE INVENTSIZE SET DESCRIPTION=?,RECVERSION=? WHERE ((((DATAAREAID=?) AND (ITEMID=?)) AND (INVENTSIZEID=?)) AND (RECVERSION=?)) [ID=11, 已重用=否]
这应该说明问题出在update_recordset没有成功降级成while select 语句。
尝试更新了一下其他字段:
static void UpdateSizes(Args _args)
{
InventSize inventSize;
;
ttsbegin;
update_recordset inventSize
setting name = 'update_recordset test'
where inventSize.ItemId == 'PB-Metal Shade';
ttscommit;
}
上面的例子更新了inventSize的name字段,该方法执行了两条SQL语句,一条查询一条更新。{
InventSize inventSize;
;
ttsbegin;
update_recordset inventSize
setting name = 'update_recordset test'
where inventSize.ItemId == 'PB-Metal Shade';
ttscommit;
}
说明顺利完成了降级为while select的操作,正常更新了相应记录。
综上所述,造成updae_recordset不能正常降级的原因应该是字段类型的问题,对照了一下description和name两个字段,它们的基类型都是string,只不过name是stringsize属性为60的string,而description是stringsize属性为memo的string类型,两者在SQL Server2005中对应的类型分别为nvarchar(60)和nText。
尝试把字段description对应EDT的stringsize改成某个长度而不是memo,update_recordset就可以顺利降级了。
测试了其他的类型int,real,date,time,enum,container,其中int,real,date,time,enum没有问题,在测试container的时候郁闷的事情又发生了,给inventsize添加一个container类型的字段containertest,重载inventsize的update方法,执行如下方法:
static void UpdateSizes(Args _args)
{
InventSize inventSize;
;
ttsbegin;
update_recordset inventSize
setting containertest = [2,4]
where inventSize.ItemId == 'PB-Metal Shade';
ttscommit;
}
执行后AOS当掉了,查看事件查看器,在系统日志中得到如下信息:{
InventSize inventSize;
;
ttsbegin;
update_recordset inventSize
setting containertest = [2,4]
where inventSize.ItemId == 'PB-Metal Shade';
ttscommit;
}
事件类型: 错误
事件来源: Service Control Manager
事件种类: 无
事件 ID: 7034
描述:
服务 Dynamics Server$01-Dynamics 意外停止。这发生了 3 次。
有关更多信息,请参阅在 http://go.microsoft.com/fwlink/events.asp 的帮助和支持中心。
事件来源: Service Control Manager
事件种类: 无
事件 ID: 7034
描述:
服务 Dynamics Server$01-Dynamics 意外停止。这发生了 3 次。
有关更多信息,请参阅在 http://go.microsoft.com/fwlink/events.asp 的帮助和支持中心。
在控制命令行里用sc query aos$01查看WIN32_EXIT_CODE ,得到如下结果:
SERVICE_NAME: aos$01
TYPE : 10 WIN32_OWN_PROCESS
STATE : 1 STOPPED
(NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN))
WIN32_EXIT_CODE : 1067 (0x42b)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x0
运行net helpmsg 1067查看具体的帮助信息得到如下信息:
进程意外终止
这个信息没啥帮助。
查看应用程序日志:
事件类型: 错误
事件来源: Application Error
事件种类: (100)
事件 ID: 1000
计算机: ADSERVER
描述:
错误应用程序 Ax32Serv.exe,版本 4.0.2163.0,错误模块 Ax32Serv.exe,版本 4.0.2163.0,错误地址 0x00322810。
有关更多信息,请参阅在 http://go.microsoft.com/fwlink/events.asp 的帮助和支持中心。
数据:
0000: 41 70 70 6c 69 63 61 74 Applicat
0008: 69 6f 6e 20 46 61 69 6c ion Fail
0010: 75 72 65 20 20 41 78 33 ure Ax3
0018: 32 53 65 72 76 2e 65 78 2Serv.ex
0020: 65 20 34 2e 30 2e 32 31 e 4.0.21
0028: 36 33 2e 30 20 69 6e 20 63.0 in
0030: 41 78 33 32 53 65 72 76 Ax32Serv
0038: 2e 65 78 65 20 34 2e 30 .exe 4.0
0040: 2e 32 31 36 33 2e 30 20 .2163.0
0048: 61 74 20 6f 66 66 73 65 at offse
0050: 74 20 30 30 33 32 32 38 t 003228
0058: 31 30 10
事件来源: Application Error
事件种类: (100)
事件 ID: 1000
计算机: ADSERVER
描述:
错误应用程序 Ax32Serv.exe,版本 4.0.2163.0,错误模块 Ax32Serv.exe,版本 4.0.2163.0,错误地址 0x00322810。
有关更多信息,请参阅在 http://go.microsoft.com/fwlink/events.asp 的帮助和支持中心。
数据:
0000: 41 70 70 6c 69 63 61 74 Applicat
0008: 69 6f 6e 20 46 61 69 6c ion Fail
0010: 75 72 65 20 20 41 78 33 ure Ax3
0018: 32 53 65 72 76 2e 65 78 2Serv.ex
0020: 65 20 34 2e 30 2e 32 31 e 4.0.21
0028: 36 33 2e 30 20 69 6e 20 63.0 in
0030: 41 78 33 32 53 65 72 76 Ax32Serv
0038: 2e 65 78 65 20 34 2e 30 .exe 4.0
0040: 2e 32 31 36 33 2e 30 20 .2163.0
0048: 61 74 20 6f 66 66 73 65 at offse
0050: 74 20 30 30 33 32 32 38 t 003228
0058: 31 30 10
通过系统和应用程序的日志还真整不明白到底是什么原因造成的服务意外终止。
综上所述,AX在处理update_recordset降级的时候有两个问题:
1.如果字段类型是string且stringsize属性为memo,则只会执行select动作,不会执行更新动作;
2.如果字段类型是container类型,则会引发AOS服务的意外终止。
换了几个环境测试都存在上述问题,按理说原书的作者应该测试过书中所举的例子,不知道是不是还需要配置什么信息,如果配置都正确的话应该就是AX平台的bug或者局限性了。