c#-在事务内部插入SqlBulkCopy会阻止对表进行任何其他写操作
作者:互联网
在我的Web应用程序中,用户可以一次插入大量数据,以提高性能,我正在使用SqlBulkCopy类.对于单个操作插入到两个不同的表中,它将运行多次.如果用户取消操作或操作失败,那么我需要回滚数据,以便使用隔离级别快照将所有内容包装在事务中.
据我了解,使用快照隔离将允许其他用户同时对表进行写/读.但是,在进行一次数据上传时,它将阻止对表的任何其他写入,直到整个父事务完成为止.
这是一些显示该问题的简化代码.我排除了许多功能,但想法仍然相同.我遍历了一些in内存集合,将它们批量复制到表中,取出它们,然后批量复制到另一个表中.
using (var transaction = myDbContext.Database.BeginTransaction(
System.Data.IsolationLevel.Snapshot))
{
var myCollectionOfObjects;
while(!GetData(ref myCollectionOfObjects))
{
SqlBulkCopy bulkCopy = new SqlBulkCopy(myCon, transaction);
//Sets the columns + rows
SetUp(bulkCopy);
bulkCopy.WriteToServer();
//After the bulkcopy operation is complete
// we retrieve the rows inserted and do another bulk copy to a different table
var recentlyAddedRows = GetRecentlyAddedRow();
SqlBulkCopy otherTableBulkCopy = new SqlBulkCopy(myCon, transaction);
SetUpBulkCopyForOtherTable(otherTableBulkCopy);
otherTableBulkCopy.WriteToServer();
}
transaction.Commit();
}
因此,如果一个用户当前在该事务中,即使它正在回滚,也会阻止对该表的所有其他写事务,因此其他执行相同功能或尝试写入该表的用户也将被阻止.
这是预期的行为,并且有一种解决方法吗?
编辑
通过查看在SQL中应用的锁,这似乎是由于bulkcopy类导致在表对象上设置了排他锁(X),就像您一次插入一个锁一样,仅应用了意图锁在桌子上(IX).仍然不确定是否可以解决此问题,但是我认为这是由于锁升级所致.
在我的一些测试中,更改表索引上的“允许”页面锁和更改批量副本的批处理大小已经完全锁定了,但它们是有气质的.
解决方法:
IsolationLevel仅引用读取,而不引用写入.如果您的一个客户端正在写入数据,则另一个客户端应该能够像开始事务之前一样读取数据,但是,它将不能同时写入数据.
标签:sqlbulkcopy,asp-net,sql,c,sql-server 来源: https://codeday.me/bug/20191119/2035237.html