De um aplicativo .NET 3.5 / C #, gostaria de capturar, SqlException
mas somente se for causado por deadlocks em uma instância do SQL Server 2008.
A mensagem de erro típica é Transaction (Process ID 58) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
Ainda assim, não parece ser um código de erro documentado para essa exceção.
Filtrar exceção contra a presença da palavra-chave de deadlock em sua mensagem parece uma maneira muito desagradável de atingir esse comportamento. Alguém conhece a maneira certa de fazer isso?
.net
sql-server-2008
deadlock
try-catch
sqlexception
Joannes Vermorel
fonte
fonte
select * from master.dbo.sysmessages where error=1205
Respostas:
O código de erro específico do Microsft SQL Server para um deadlock é 1205, então você precisa lidar com o SqlException e verificar isso. Então, por exemplo, se para todos os outros tipos de SqlException você quiser que a exceção seja exibida:
Ou, usando a filtragem de exceção disponível em C # 6
Uma coisa útil a fazer para encontrar o código de erro SQL real para uma determinada mensagem é olhar em sys.messages no SQL Server.
por exemplo
Uma maneira alternativa de lidar com deadlocks (do SQL Server 2005 e superior) é fazer isso dentro de um procedimento armazenado usando o suporte TRY ... CATCH:
Há um exemplo completo aqui no MSDN de como implementar a lógica de nova tentativa de deadlock puramente no SQL.
fonte
SqlException
pode ser empacotado em outra. Portanto, podemos precisar capturar qualquer tipo de exceção e verificá-los, se eles não forem diretamente uma exceção de deadlock, verifique recursivamente os delesInnerException
.Como suponho que você queira detectar bloqueios, para poder tentar novamente a operação que falhou, gostaria de avisá-lo para um pequeno pegadinho. Espero que me desculpem por estar um pouco fora do assunto aqui.
Um deadlock detectado pelo banco de dados reverterá efetivamente a transação na qual você estava executando (se houver), enquanto a conexão é mantida aberta no .NET. Tentar novamente essa operação (na mesma conexão) significa que ela será executada em um contexto sem transação e isso pode levar à corrupção de dados.
É importante estar ciente disso. É melhor considerar a conexão completa condenada no caso de uma falha causada por SQL. A nova tentativa da operação só pode ser feita no nível em que a transação está definida (recriando essa transação e sua conexão).
Portanto, quando estiver tentando novamente uma operação com falha, certifique-se de abrir uma conexão completamente nova e iniciar uma nova transação.
fonte
Aqui está uma maneira C # 6 de detectar deadlocks.
Certifique-se de que este try..catch envolva toda a transação. De acordo com @Steven (veja sua resposta para detalhes), quando o comando sql falha devido ao deadlock, ele faz com que a transação seja revertida e, se você não recriar a transação, sua nova tentativa será executada fora do contexto de a transação e pode resultar em inconsistências de dados.
fonte