c# - SqlBulkCopy 在事务内部插入时阻止任何其他对表的写入

标签 c# sql asp.net sql-server sqlbulkcopy

在我的网络应用程序中,用户可以一次插入大量数据,以提高性能,我正在使用 SqlBulkCopy 类。对于插入两个不同表的单个操作,它会运行多次。如果用户取消操作或操作失败,那么我需要回滚数据,因此我使用隔离级别快照将所有内容包装在一个事务中。

据我了解,使用快照隔离将允许其他用户同时写入/读取表。然而,当一个数据上传发生时,它会阻止任何其他对表的写入,直到整个父事务完成。

这里是一些显示问题的简化代码。我排除了很多功能,但想法保持不变。我迭代了一些内存中的集合,将它们批量复制到一个表,检索它们,然后批量复制到另一个表。

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 仅指读取而不是写入。如果您的一个客户端正在写入数据,那么另一个客户端应该能够读取事务开始前的数据,但是,它不能同时写入。

关于c# - SqlBulkCopy 在事务内部插入时阻止任何其他对表的写入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34227800/

相关文章:

mysql - 按过去 7 天内的日期选择条目

mysql - 如何在 MySQL 中排序子查询?

c# - nHibernate (w/CaSTLe ActiveRecord) with C# interfaces (esp for DTO's)

c# - RestSharp 无效的 URI : The URI Scheme is not valid

c# - 数据库中的重复项

c# - 使用 Linq + group by 查询容器?

sql - 选择每一列,但重命名其中之一

javascript - 对动态填充的列表框进行排序

c# - 如何将 NameValueCollection 转换为 JSON 字符串?

c# - excel表格数据删除问题