在AX中可以不局限于当前的会话公司而跨公司查询数据,使用跨公司查询有几种方式:
- 在x++ select语句中使用crossCompany关键字
- Query class的实例使用true调用allowCrossCompany。QueryRun也有个属性allowCrossComany,它总是读写操作其下Query的allowCrossCompany属性,两者是等价的。
- AOT中的Query对象AllowCrossCompany设为true
- Form Data souce的节点CrossCompanyAutoQuery设为true,或者使用数据源的方法FormDataSource.crossCompanyAutoQuery
跨公司查询得到的结果类似对公司依次做union查询,但仅是那些用户被授权访问的公司数据。
使用crossComapny的具体语法是:
static void JobDemoCrossCompany(Args _args) { BankAccountTable tabBAT; // saveDataPerCompany == true. container conCompanies = [ 'cm1', 'cm2', 'dat' ]; str 4 sCompanyPrevious = " "; // Maximum length is 4 characters. int iCountCompanies = 0; ; while select crossCompany : conCompanies * from tabBAT order by dataAreaId { if ( sCompanyPrevious != tabBAT.dataAreaId ) { info( tabBAT.dataAreaId + " = tabBAT.dataAreaId" ); iCountCompanies++; if ( iCountCompanies >= 2 ) { break; } sCompanyPrevious = tabBAT.dataAreaId; } } return; }
可以在crosscompany关键字后紧跟一个container来限定所访问公司的列表。
使用Query Class的例子:
static void JobDemoAllowCrossCompany(Args _args) { BankAccountTable tabBAT; // saveDataPerCompany == true. Query qry2; QueryBuildDataSource qbds3; QueryRun qrun4; str sCompanyPrevious = " "; int iCountCompanies = 0; int iTableNumBAT; ; qry2 = new Query(); qry2.allowCrossCompany( true ); qry2.addCompanyRange( 'dat' ); qry2.addCompanyRange( 'twf' ); iTableNumBAT = tableNum( BankAccountTable ); qbds3 = qry2 .addDataSource( iTableNumBAT ); //qbds3.company( 'dat' ); qrun4 = new QueryRun( qry2 ); while ( qrun4.next() ) { if ( qrun4.changed( iTableNumBAT ) ) { tabBAT = qrun4.get( iTableNumBAT ); if ( sCompanyPrevious != tabBAT.dataAreaId ) { print( tabBAT.dataAreaId + " = tabBAT.dataAreaId" ); iCountCompanies++; if ( iCountCompanies >= 2 ) { break; } sCompanyPrevious = tabBAT.dataAreaId; } } } pause; return; }
注意这里是使用Query.addCompanyRange()方法添加查询限定的公司。
delete_from、insert_recordset、update_recordset这些操作是不能够使用corsscompany关键字的,但是可以使用while select crosscompany得到纪录后逐条操作,比如:
static void JobCCForUpdMethod( Args _args ) { Table21 tab21; ; ttsBegin; while select forUpdate crossCompany countOfReviews from tab21 { changeCompany( tab21 .dataAreaId ) { tab21 .countOfReviews = tab21 .countOfReviews + 2; tab21 .update(); } } ttsCommit; }
在更新纪录前注意使用changecompany()切换当前会话公司,这是x++的保留关键字,由它随后的{}标识出代码运行的公司环境,出了这个区域就恢复到当前会话的公司。AOT中Query的data source有个company属性,这里可以填入查询的公司,类似于changeCompany所起的作用,但是如果Query已经设置了AllowCrossCompany,再填入data source的company会编译错误,这两者是相互矛盾的。
在上面的操作中,使用了table.dataAreaId来得到相应的公司名称,还有一个getcompany(table.tableid)方法得到纪录的公司,需要特别注意这两个方法得到的结果可能会不同,前者确确实实是保存在数据库纪录中的数据,后者会因为表的共享类型不同会有所不同。对全局表SaveDataPerComany为no,表没有dataAreaId,两者总是返回当前会话公司;指定公司的表,SaveDataPerCompany为yes,这种表可能通过虚拟公司共享,表纪录的dataAreaId保存的可能是实际公司的名称,这时getcompany得到的是dataareaid字段的公司,而如果dataareaid保存的是虚拟公司的名称,getcompany得到的数据则会有多种情况:
Test case number |
dataAreaId in shared table's current row |
Current session company |
Returned by company getter method |
---|---|---|---|
1 |
VC9 |
CM1 |
CM1 |
2 |
VC9 |
CM2 |
CM2 |
3 |
VC9 |
CM3 |
Either CM1 or CM2, whichever the user has greater permissions on |
4 |
CM3 |
(Any company) |
CM3 |
这里VC9是一个虚拟的公司,包含在真实的公司CM1和CM2,1、2两者情况因为当前会话公司包含VC9,所以得到的结果是当前会话公司,但是如果当前会话公司不包含虚拟公司VC9,得到的结果就是在哪个真实公司对表的权限越大就返回哪个真实公司,比如插入数据优先于读取,但是不管是哪种情况,getcompany总是返回真实的公司,因此在使用getcomany时需要特别留意虚拟公司的情况。
更多的内容可见http://msdn.microsoft.com/en-us/library/cc634544.aspx。