Using SqlBulkCopy in one transaction for multiple, related tables

我只是一个虾纸丫 提交于 2021-02-11 08:45:26

问题


I'm a bit stuck here trying to copy lots of data (a million records total) from three related tables to other three related tables in the same database.

My table design is as follows:

What I need is to be able to copy data from the draft tables over to the non-draft tables in one transaction which I'm able to roll back if anything goes wrong. This is needed because we don't want i.e. Billing and BillingPriceLine records to exist in the database, if the bulk insertion of BillingPriceLineSpecificationDraft copy failed.

However, since I'm using SqlBulkCopy for copying the records, I am not able to get a hold of the new IDs to make the correct relations between the three new tables. If I perform a read on i.e. the Billing table in the transaction to get the correct Billing ID, I get a time out, which is expected since the tables are locked within the transaction.

I have tried setting the IsolationLevel enum on the transaction (in fact, I went crazy and tried them all ;-)), but they didn't do anything it seems.

Is there any good way of doing this that I'm missing?

Thanks in advance.


回答1:


You can not really do that with bulk copy.

You also do not need to - it is a very bad practice to touch real tables with SqlBulkCopy because whoever wrote that thing, has no understanding of SQL Server locking mechanisms.

  • Create 3 temporary tables with the same table structure as the target.
  • SqlBulkCopy into those tables (thus avoiding SqlBulkCopy locking screwing you and avoiding the transaction issue).
  • Then, in one transaction, issue 3 INSERT INTO statements using the data from the temporary tables as source.

Result is the best of both worlds. Once you have the data in the temporary tables (with possibly fake ID's) you can pull some really interesting SQL to upate the source table in one transaction with the relevant internal ID's for the next table. The SQL gets complex, but this is the best you can do.


Explanation why SqlBulkCopy is bad:

SqlBulkCopy really is highly problematic - it does screw locking. It demands an exclusive table lock (which is "sort of ok"). It asks for it - but it never waits (i.e. if there is any lock on the table, this fails), then it tries again.... after some time.... until a timeout expires. The result is that on a table with activity it is really hard to get SqlBulkCopy to get ANY lock. The proper code would be to wait for the exclusive lock... well.



来源:https://stackoverflow.com/questions/37188875/using-sqlbulkcopy-in-one-transaction-for-multiple-related-tables

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!