Тупик с Entity Framework при параллельной вставке нескольких строк - PullRequest
3 голосов
/ 29 декабря 2011

У нас проблема с вставкой нескольких объектов с 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 дает нам вставку, а затем выбор. Поскольку это делается параллельно, многие из них прерываются из тупика.

Мы используем EF 4.0, а не 4.1 или 4.2.

Есть идеи, как это решить? Я видел это, но оно довольно старое: http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/4f634d8f-1281-430b-b664-ec7ca413b387/

Ответы [ 3 ]

2 голосов
/ 19 января 2012

В конце проблема была с взаимоблокировками в сериализуемой транзакции, не имеющей ничего общего с созданием идентификатора.

Здесь я объясню проблему: http://pablocastilla.wordpress.com/2012/01/19/deadlocks-in-serializable-transactions-with-sql-server/

2 голосов
/ 14 ноября 2012

Я думаю, причина в том, что CommandRequestId не является первичным ключом. Если вы установите его в качестве первичного ключа, вы не получите мертвую блокировку. У меня была та же проблема, и когда я установил столбец Identity в качестве первичного ключа, он работал нормально.

2 голосов
/ 29 декабря 2011

Ситуация все та же. EF не имеет никаких дополнительных функций, чтобы избежать этого. Таким образом, ваше решение может быть:

  • Ручная синхронизация в сервисе, так что только один звонок может вставить запись за раз. Это довольно уродливо и очень сильно повлияет на пропускную способность, но это довольно простое решение - реализовать простую пессимистическую блокировку только для этой единственной операции, поэтому это зависит от типа приложения, которое вы создаете.
  • Выбор, который вы видите в конце, вызван использованием автоматически сгенерированного идентификатора. EF необходимо сообщить об этом удостоверении личности. Вы не можете отключить эту функцию только для вставки. То, что вы можете сделать, это не использовать автоматически сгенерированные идентификаторы в базе данных и обрабатывать генерацию идентификаторов в вашем приложении. Вы переместите генерацию идентификатора за пределы DB / EF и получите полный контроль над его синхронизацией. После этого вы больше никогда не увидите этот выбор (вы также должны установить StoreGeneratedPattern для свойства Id на None). Например, вы можете реализовать собственный алгоритм HiLo Id .
...