4

EF を使用して複数のエンティティを並行して挿入する際に問題が発生しています。WCF 操作は、多くのプロセスによって呼び出され、各呼び出しで異なる分散トランザクションを持つエンティティを生成します。SQL サーバー プロファイラーで確認できるように、次の 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 は挿入を行い、後で選択を行います。並行して行われるため、それらの多くはデッドロックによって中止されます。

4.1 や 4.2 ではなく、EF 4.0 を使用しています。

これを解決する方法はありますか?私はこれを見たことがありますが、かなり古いものです: http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/4f634d8f-1281-430b-b664-ec7ca413b387/

4

3 に答える 3

3

その理由は CommandRequestId が主キーではないためだと思います。主キーとして設定すると、デッドロックは発生しません。同じ問題があり、Identity 列を主キーとして設定すると、正常に機能しました。

于 2012-11-14T16:40:25.983 に答える
2

状況は今も同じです。EF には、これを回避するための追加機能はありません。したがって、ソリューションは次のようになります。

  • 一度に 1 つの呼び出しだけがレコードを挿入できるように、サービスで手動で同期します。これはかなり醜く、スループットに大きく影響しますが、この単一の操作に対してのみ単純な悲観的ロックを実装するのは非常に簡単な解決策であるため、構築しているアプリケーションのタイプによって異なります。
  • 最後に表示される選択は、自動生成された ID を使用することによって発生します。この ID について EF に通知する必要があります。挿入のみのためにこの機能をオフにすることはできません。できることは、データベースで自動生成された ID を使用せず、アプリケーションで ID 生成を処理することです。Id 生成を DB/EF の外に移動すると、その同期を完全に制御できます。その後、この選択が再び表示されることはありません ( StoreGeneratedPatternId プロパティを に設定する必要もありますNone)。たとえば、カスタムHiLo Id アルゴリズムを実装できます。
于 2011-12-29T18:29:43.643 に答える
2

最後に、問題はシリアル化可能なトランザクションのデッドロックにあり、ID の作成とは関係ありませんでした。

ここで問題を説明します: http://pablocastilla.wordpress.com/2012/01/19/deadlocks-in-serializable-transactions-with-sql-server/

于 2012-01-19T10:20:55.280 に答える