Farseer

导航

第十七章:性能(四)

本文仅供AX从业者和爱好者学习讨论之用,由于原文版权问题,请勿转载。

RecordInsertList和RecordSortedList类

当向一个表中插入多条记录时,除了采用批操作符,DynamicsAX还允许使用RecordInsertList和RecordSortedList类。当准备插入记录时,DynamicsAX应用运行时将多条记录打包到一个包中并将其发送到数据库。数据库为包中的每一条记录执行单独的插入语句。下面的例子显示了这一点,在这个例子中,实例化了一个RecordInsertList对象,并且将要插入到数据库中的记录添加到RecordInsertList对象中。当所有的对象都被插入到该对象后,调用insertDatabase方法确保所有的记录插入到数据库中。
static void CopySizes(Args _args)
{
    InventSize inventSizeTo;
    InventSize inventSizeFrom;
    InventTable inventTable;
    RecordInsertList recordInsertList;
    ;
    ttsbegin;
    recordInsertList 
= new RecordInsertList(tableNum(InventSize));
    
    
while select itemId from inventTable
            where inventTable.ItemId 
== 'PB-Metal Shade'
        join inventSizeId,description,name from inventSizeFrom
            where inventSizeFrom.ItemId 
== 'PB-PlasticShade'
    
{
        inventSizeTo.ItemId 
= inventTable.ItemId;
        inventSizeTo.InventSizeId 
= inventSizeFrom.InventSizeId;
        inventSizeTo.Name 
= inventSizeFrom.Name;
        recordInsertList.add(inventSizeTo);
    }

    recordInsertList.insertDatabase();
    
    ttscommit;

}
当DynamicsAX应用运行时发现添加到RecordInsertList对象的记录足够组成一个包的时候,记录被打包,发送到数据库,然后在数据库层一条条插入。该检测发生在在add方法被调用时。当应用逻辑调用insertDatabase方法时,剩余的记录采用相同的机制插入。
采用这些类比起while select有个好处:由于多条记录同时发送从而减少了从AOS发送到数据库的来回次数。但是,数据库执行的insert语句是相同的。
注释:由于记录插入数据库的时间依赖于记录缓存(译注:record buffer)和包的大小,所以不能期望在调用insertDatabase方法调用之前可以数据库中的选择某条记录
前面提到的场景可以用RecordSortedList类重写取代RecordInsertList类,代码如下:
static void CopySizes(Args _args)
{
    InventSize inventSizeTo;
    InventSize inventSizeFrom;
    InventTable inventTable;
    RecordSortedList recordSortedList;
    ;
    ttsbegin;
    recordSortedList 
= new RecordSortedList(tableNum(InventSize));
    recordSortedList.sortOrder(fieldNum(InventSize,ItemId),
                               fieldNum(InventSize,InventSizeId));
    
while select itemId from inventTable
            where inventTable.ItemId 
== 'PB-Metal Shade'
        join inventSizeId,description,name from inventSizeFrom
            where inventSizeFrom.ItemId 
== 'PB-Plastic Shade'
    
{
        inventSizeTo.ItemId 
= inventTable.ItemId;
        inventSizeTo.InventSizeId 
= inventSizeFrom.InventSizeId;
        inventSizeTo.Description 
= inventSizeFrom.Description;
        inventSizeTo.Name 
= inventSizeFrom.Name;
        recordSortedList.ins(inventSizeTo); 
//No record will be inserted
    }

    recordSortedList.insertDatabase(); 
//All records are inserted in database
    ttscommit;


}
(译注:我在运行上述代码的时候出现了错误,错误信息为:“无法创建大小(inventSize)中的记录,若要使用databaseInsert()方法,必须在服务器端实例化RecordSortedList”。将示例代码放到类中并让其运行在服务器端就可以顺利执行了,不知道原作者有没有测试过上面的这段示例代码还是配置或者其他的原因,并且报错信息里居然是方法databaseInsert(),而不是实际调用的insertDatabase())
当应用逻辑使用RecordSortedList对象时,直到调用insertDatabase()方法时才会将记录传递并插入到数据库中。往返次数和插入的插入语句的条数跟RecoreInsertList对象一样(译注:按照前面的描述,往返次数应该是不一样的)。
RecordInsertList和RecordSortedList对象可能在应用程序逻辑中被降级为逐条插入,在这种情况下,每条记录都要用一个单独的往返发送到数据库随后执行一条INSERT语句。如果inser或者aosValidateInsert方法被重载,或者表中包含container或者memo类型的字段会发生降级。数据库日志配置用来记录插入操作或者在该表上配置了由插入操作触发的预警并不会导致降级的发生。在记录被发送插入到数据库后数据库日志和事件(译注:预警)逐条处理。
在实例化RecordInsertList对象时,可以指定跳过insert和aosValidateInsert方法。如果操作没有被降级也可以指定跳过数据库日志和事件(译注:预警)。( 译注:第一点没什么问题,如果重载了insert方法,将RecordInsertList的new方法的第二个参数设为true,则可以避免降级。对于第二点,将第三个参数设为true,即使操作没有被降级,依然会将其记录在数据库日志表中,不是很清楚作者为什么说可以跳过,还需要设置其他地方?)

posted on 2007-05-09 01:08  佛西亚  阅读(655)  评论(1编辑  收藏  举报