Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/security/4.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
Entity framework 4 并行插入多行时实体框架死锁_Entity Framework 4_Database Deadlocks - Fatal编程技术网

Entity framework 4 并行插入多行时实体框架死锁

Entity framework 4 并行插入多行时实体框架死锁,entity-framework-4,database-deadlocks,Entity Framework 4,Database Deadlocks,我们在并行插入几个实体时遇到问题。WCF操作由许多进程调用,以在每次调用中生成具有不同分布式事务的实体。正如我们在sql server探查器中看到的,它生成以下sql: (@0 int,@1 nvarchar(32),@2 datetime2(7),@3 nvarchar(64),@4 int,@5 int,@6 bit) insert [dbo].[CommandRequests]( [CommandId] , [DeviceId] , [StartDateTime] , [End

我们在并行插入几个实体时遇到问题。WCF操作由许多进程调用,以在每次调用中生成具有不同分布式事务的实体。正如我们在sql server探查器中看到的,它生成以下sql:

(@0 int,@1 nvarchar(32),@2 datetime2(7),@3 nvarchar(64),@4 int,@5 int,@6 bit)
insert [dbo].[CommandRequests](
   [CommandId]
 , [DeviceId]
 , [StartDateTime]
 , [EndDateTime]
 , [Parameters]
 , [Caller]
 , [Result]
 , [Priority]
 , [Timeout]
 , [ParentRequestId]
 , [IsSuccessful]
 , [Host])
  values (@0, @1, @2, null, null, @3, null, @4, @5, null, @6, null)

  select [CommandRequestId]
  from [dbo].[CommandRequests]
  where @@ROWCOUNT > 0 and [CommandRequestId] = scope_identity()   
所以EF给我们一个插入,然后给我们一个选择。因为它是并行完成的,所以它们中的许多被死锁中止

我们使用的是EF4.0,而不是4.1或4.2

你知道怎么解决这个问题吗?我见过这个,但它很古老:
情况还是一样。EF没有任何其他功能来避免这种情况。因此,您的解决方案可以是:

  • 服务中的手动同步,以便一次只能插入一个呼叫记录。这是非常难看的,它将极大地影响吞吐量,但只为这一个操作实现简单的悲观锁定是非常容易的解决方案,所以它取决于您正在构建的应用程序的类型
  • 您在末尾看到的选择是由使用自动生成的ID引起的。需要将此ID告知EF。您不能仅在插入时关闭此功能。您可以不在数据库中使用自动生成的Id,而是在应用程序中处理Id生成。您将把Id生成移到DB/EF之外,并且您将完全控制其同步。此后,您将再也看不到此选择(您还必须将Id属性的
    StoreGeneratedPattern
    设置为
    None
    )。例如,您可以实现自定义

最后,问题在于可序列化事务中的死锁,与id的创建无关

我在这里解释问题:

我认为原因是CommandRequestId不是主键。如果您将其设置为主键,则不会得到死锁。我也遇到了同样的问题,当我将Identity列设置为主键时,效果很好。

我们正在考虑将select查询更改为:select scope_Identity()作为[CommandRequestId],其中@@ROWCOUNT>0您认为如何?该查询是由EF自动生成的。您想如何更改它?您可以使用函数在模型中更改它,我们已经这样做了,并且它可以工作。您的意思是将存储过程映射到insert操作?不,这是类似的,但是您用模型的xml编写查询。插入[dbo]。[CommandRequests]([CommandId]…)值(…)选择范围_identity()作为[CommandRequestId],其中@@ROWCOUNT>0