Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么以下SQL Server在事务中运行时会插入死锁?_C#_Sql Server_Linq To Sql_Deadlock_Transactionscope - Fatal编程技术网

C# 为什么以下SQL Server在事务中运行时会插入死锁?

C# 为什么以下SQL Server在事务中运行时会插入死锁?,c#,sql-server,linq-to-sql,deadlock,transactionscope,C#,Sql Server,Linq To Sql,Deadlock,Transactionscope,我当前正在将一条记录插入SQL Server表中,然后选择自动增量ID,如下所示: (@p0 int,@p1 nvarchar(8))INSERT INTO [dbo].[Tag]([Some_Int], [Tag]) VALUES (@p0, @p1) SELECT CONVERT(Int,SCOPE_IDENTITY()) AS [value] (这是使用Linq到SQL生成的)。出于某种原因,当我在事务中使用TransactionScope对象和可序列化隔离级别运行此代码时,SQL

我当前正在将一条记录插入SQL Server表中,然后选择自动增量ID,如下所示:

(@p0 int,@p1 nvarchar(8))INSERT INTO [dbo].[Tag]([Some_Int], [Tag])
VALUES (@p0, @p1)

SELECT CONVERT(Int,SCOPE_IDENTITY()) AS [value] 
(这是使用Linq到SQL生成的)。出于某种原因,当我在事务中使用TransactionScope对象和可序列化隔离级别运行此代码时,SQL Server会抛出死锁错误。我分析了死锁图事件,发现所涉及的两个进程都在等待对方执行转换操作,因为我了解以下信息:

<resource-list>
   <keylock hobtid="72057594101170176" dbid="5" objectname="foo.dbo.Tag" indexname="PK_Tag_1" id="lockb77cdc0" mode="RangeS-S" associatedObjectId="72057594101170176">
    <owner-list>
     <owner id="processc9be40" mode="RangeS-S"/>
    </owner-list>
    <waiter-list>
     <waiter id="processc9ae38" mode="RangeI-N" requestType="convert"/>
    </waiter-list>
   </keylock>
   <keylock hobtid="72057594101170176" dbid="5" objectname="foo.dbo.Tag" indexname="PK_Tag_1" id="lockb77cdc0" mode="RangeS-S" associatedObjectId="72057594101170176">
    <owner-list>
     <owner id="processc9ae38" mode="RangeS-S"/>
    </owner-list>
    <waiter-list>
     <waiter id="processc9be40" mode="RangeI-N" requestType="convert"/>
    </waiter-list>
   </keylock>
  </resource-list>

我的理解是,在第一个进程完成插入和选择标识之前,事务作用域将阻止第二个进程执行插入。然而,情况似乎并非如此。有谁能告诉我如何以线程安全的方式实现我的需求呢

--已更新--

请注意;我99%确信两个进程之间没有共享连接,因为每个进程都创建了一个新的DataContext来与数据库通信

--再次更新--

Remus Rusanu指出,一些遗漏的信息与问题有关,我试图根据死锁图报告简化场景,但我在这里扩展了解释。在执行插入之前,我对相关表执行exists查询,以确定标记是否已经存在。如果是这样,我就结束交易。如果没有,则应该继续插入,然后我在一个表上执行一个更新(此处未显示),该表的主键为
Some_Int
,尽管该更新仅针对最后修改的值。标记表有一个由auto inc ID和一些Int组成的聚集索引可能也很重要。我不认为最后一条信息是相关的,因为我尝试将表更改为仅将auto inc字段作为主键/聚集索引,但没有任何效果


谢谢。

您根本不需要交易。
scope\u identity()
函数将返回上次在同一作用域中创建的id,因此,如果在获取id之前执行另一个插入,则不会有问题,因为该id位于不同的作用域中。

所讨论的“convert”是一个函数,与“convert”函数没有任何关系。在PK_Tag_1索引上已经放置了RangeS-S锁,这表明您所做的不仅仅是插入。在尝试插入之前,您的事务是否会首先检查新记录是否存在?

检查查询中使用的isolationLevel。请注意,TransactionScope在默认情况下使用可序列化的隔离级别()。尝试将事务的隔离级别更改为committed。

这是个好问题!我想看一个答案。事务作用域是这样,如果其他地方出了问题,或者至少在uni测试完成时,我可以回滚更改。@downvoter:为什么要进行downvote?如果你不说你认为是错的,那就不能以任何方式改进答案。我更新了问题以更全面地反映情况。我已将隔离级别更改为快照,这似乎缓解了我的死锁问题。感谢您的帮助:)另外,我意识到快照隔离不会阻止重复标记与同一实体关联的情况。为此,我将创建一个唯一的键约束,并优雅地处理潜在的错误