salesFormLetter.update(SalesTable::find(salesId));
}
}
salesLine.insert();
comrs.moveNext();
}
}
}
1.新建一个类,随便取什么名字,比如叫ChangeCompanyProblem之类的,默认情况下该类的RunOn属性为Called from
2.重载该类的new方法,不需要修改任何代码。
3.新建一个main方法,代码如下:
select firstonly salesLine;
}
}
这里的sleep方法,只是模拟正常情况下的一些耗时的计算,假设从select firstonly salesTable运行到problem = new ChangeCompanyProblem()需要10S,这个在一般的场景中应该是比较常见的。
4.新建一个MenuItem让其指向该类,默认情况下该MenuItem的RunOn属性为Client
5.在MainMenu中新建菜单项让其指向该MenuItem
6.在AX的标准菜单(实际上如果不通过AX的标准菜单项而是在AOT里直接打开菜单或者菜单项是不会出问题的)中打开该菜单项,在运行的时候点击客户端界面,随便点哪里,比如其他的菜单项之类的。
7.如果当前公司是"002",应该会出现如下提示:
从上面的步骤可以看出,应该是在实例化类ChangeCompanyProblem的时候把当前公司从001切换到了002,在类ChangeCompanyProblem的new方法和类Application的setDefaultCompany里加断点跟踪也可以得出这样的结论。
将类ChangeCompanyProblem的Runon属性变成Server或者不重载类的new方法,再实例化的时候也就不会切换当前公司了,于是得出如下结论:
如果通过AX的标准菜单项调用一个类实现某个功能,在切换了公司的语境下,在该类的某个方法里要实例化其他类,而被实例化的类的new方法被重载了且用户在实例化该类之前在AX界面上有其他操作(比如随便点击界面的某个地方),如果该类被实例化时发生在客户端,将会触发类Application的setDefaultCompany,导致当前公司切换至当前Client所指定的公司,这样该类被实例化后,所有的代码执行的语境将会被更改至Client的当前公司而不是ChangeCompany所指定的公司,会产生与预期不同的结果。貌似很绕口的说。。。
所以需要注意以下两点:
1.如果要在ChangeCompany包括的语句中实例化类,一定要让这些类运行在服务器端;
2.避免在ChangeCompany包括的语句中调用info,print之类的向客户端打印信息的方法,因为这也会导致application的stDefaultCompany的调用。
由于以上只是出于自己的简单测试,没有见过相应的权威的解释,没办法从原理上得到合理的解释,只是通过有限的测试得到的结果,不能保证正确性,还望高手指点。
测试版本 AX2009 SP1(RU3)