[转]lBulkCopy与Insert触发器的应用问题

sqlBulkCopy是.net2.0提供的一个快速批量插入数据的新对象。

出于这个对象主要作为作为了提高批量插入的效率,所以在默认情况下批量数据的插入并不会引发insert触发器的触发。但在有些情况下必须要用到这个触发器,这可以通过使用SqlBulkCopy (String, SqlBulkCopyOptions) 指定enum SqlBulkCopyOptions为FireTriggers解决。

在项目中有一个记账功能,每一条记录的结余数要从上一次的结余数与本次账的增减计算后得出。原来的写法是由前端对账的每一条依次插入新的记录,并利用insert触发器计算结余数。insert触发器写法如下:

select a.ParentID,max(a.Stamp) stamp  into #temp1

                            from ivInventoryItem a, inserted b

                            where a.ParentId = b.ParentID and a.OID<> b.OID

                            group by a.ParentID

select  @lastCurrentQty1 = isnull( t.CurrentQty1, 0) ,  @lastCurrentQty2 = isnull( t.CurrentQty2, 0),

         @lastCurrentQty3 = isnull( t.CurrentQty3, 0) , @lastCurrentQty4 = isnull( t.CurrentQty4, 0)

from ivInventoryItem t

         inner join #temp1 iv on t.ParentID = iv.ParentID and t.Stamp = iv.stamp

drop table #temp1

--现存数 = 上次现存数 + 收入数 -  支出数

update ivInventoryItem set CurrentQty1 = @lastCurrentQty1 +  isnull( inserted.DepositQty1,0) - isnull(inserted.WithdrawalQty1, 0),

CurrentQty2 = @lastCurrentQty2 +  isnull( inserted.DepositQty2,0) - isnull(inserted.WithdrawalQty2, 0),

CurrentQty3 = @lastCurrentQty3 +  isnull( inserted.DepositQty3,0) - isnull(inserted.WithdrawalQty3, 0),

CurrentQty4 = @lastCurrentQty4 +  isnull( inserted.DepositQty4,0) - isnull(inserted.WithdrawalQty4, 0)

from inserted where ivInventoryItem.OID = inserted.OID

*/

--现存数 = 上次现存数 + 收入数 -  支出数

update ivInventoryItem set CurrentQty1 = @lastCurrentQty1 +  isnull( inserted.DepositQty1,0) - isnull(inserted.WithdrawalQty1, 0),

CurrentQty2 = @lastCurrentQty2 +  isnull( inserted.DepositQty2,0) - isnull(inserted.WithdrawalQty2, 0),

CurrentQty3 = @lastCurrentQty3 +  isnull( inserted.DepositQty3,0) - isnull(inserted.WithdrawalQty3, 0),

CurrentQty4 = @lastCurrentQty4 +  isnull( inserted.DepositQty4,0) - isnull(inserted.WithdrawalQty4, 0)

from inserted where ivInventoryItem.OID = inserted.OID

由于系统是一个大量数量业务处理系统,当每一次记账数量较多时(>2000),此方法的性能明显出现问题。于是前端改为SqlBulkcopy,这样性能明显提高很多。但发现insert触发器不工作。原来SqlBulkcopy对象主要作为作为了提高批量插入的效率,所以在默认情况下批量数据的插入并不会引发insert触发器的触发。这可以通过使用SqlBulkCopy (String, SqlBulkCopyOptions) 指定enum SqlBulkCopyOptions为FireTriggers解决。但触发器工作后综合结余数的计算并不正确。分析上面的触发器,发现它利用了inserted临时表中的记录获取本次插入记录的上一次记录的结余。但现在由于使用SqlBulkcopy,一次插入多条记录,就不能在每次触发中从inserted中查出一条记录。实际上在一个插入或更新事务处理中,新建行被同时添加到 inserted 表和触发器表中,所以,使用SqlBulkcopy时在inserted表中是有多条记录的,且一次调用SqlBulkcopy只会有一次触发器的运行。

更改触发器如下,测试数量正常:

select a.ParentId,max(a.Stamp) stamp  into #temp1

                            from ivInventoryItem a, inserted b

                            where a.ParentId = b.ParentID and a.OID<> b.OID

                            group by a.ParentId

--现存数 = 上次现存数 + 收入数 -  支出数

update  ivInventoryItem set

CurrentQty1 = isnull(p.CurrentQty1,0) +  isnull( i.DepositQty1,0) - isnull(i.WithdrawalQty1, 0) ,

CurrentQty2 = isnull(p.CurrentQty2,0) +  isnull( i.DepositQty2,0) - isnull(i.WithdrawalQty2, 0) ,

CurrentQty3 = isnull(p.CurrentQty3,0)+  isnull( i.DepositQty3,0) - isnull(i.WithdrawalQty3, 0) ,

CurrentQty4 = isnull(p.CurrentQty4,0)+  isnull( i.DepositQty4,0) - isnull(i.WithdrawalQty4, 0)

from ivInventoryItem c,(select * from ivInventoryItem) p, #temp1 t ,inserted i

where p.ParentID = t.ParentID and p.Stamp = t.stamp and t.ParentID = i.ParentID

and c.oid = i.oid and (isnull( i.CurrentQty1, 0 ) +  isnull( i.CurrentQty2, 0 )  +  isnull( i.CurrentQty3, 0 ) +  isnull( i.CurrentQty4, 0 )  =0)

drop table #temp1

你可能感兴趣的:(JOIN,工作,.net,String,table,insert)