在一个事务中使用SqlBulkCopy为多个相关表

时间:2016-05-12 13:47:05

标签: c# sql-server database transactions

我有点卡在这里试图将三个相关表中的大量数据(总共一百万条记录)复制到同一数据库中的其他三个相关表。

我的表格设计如下:

enter image description here

我需要的是能够将草稿表中的数据复制到一个事务中的非草稿表中,如果出现任何问题我可以回滚。这是必需的,因为如果Billing副本的批量插入失败,我们不希望数据库中存在BillingPriceLineBillingPriceLineSpecificationDraft条记录。

但是,由于我使用SqlBulkCopy复制记录,因此我无法获取新ID以在三个新表之间建立正确的关系。如果我对事务中的Billing表执行读取以获取正确的Billing ID,则会超时,这是预期的,因为表在事务中被锁定。

我已经尝试在交易中设置IsolationLevel枚号(事实上,我疯了,并尝试了所有;-)),但他们似乎没有做任何事情。

有没有什么好方法可以解决这个问题?

提前致谢。

1 个答案:

答案 0 :(得分:3)

批量复制不能真正做到这一点。

您也不需要 - 使用SqlBulkCopy触摸真实表是一种非常糟糕的做法,因为无论谁编写该内容,都不了解SQL Server锁定机制。

  • 创建3个临时表,其表结构与目标相同。
  • 将SqlBulkCopy放入这些表中(从而避免SqlBulkCopy锁定,从而避免了交易问题)。
  • 然后,在一个事务中,使用临时表中的数据作为源发出3个INSERT INTO语句。

结果是两全其美的。一旦你有了临时表中的数据(可能是伪造的ID),你就可以在一个事务中提取一些非常有趣的SQL来更新源表,并为下一个表提供相关的内部ID。 SQL变得复杂,但这是你能做到的最好的。

解释为什么SqlBulkCopy不好:

SqlBulkCopy确实存在很大问题 - 它确实是螺旋锁定。它需要一个独占的表锁(这是“好的”)。它要求它 - 但它永远不会等待(即如果表上有任何锁定,这会失败),然后它再次尝试....一段时间后....直到超时到期。结果是在具有活动的表上,很难让SqlBulkCopy获得任何锁定。正确的代码是等待独占锁......好吧。