Je veux savoir comment nous identifions l'erreur de duplication de clé primaire à partir du code d'erreur SQL Server en C #.
Par exemple, j'ai un formulaire C # pour entrer des données dans une base de données SQL Server. Quand une erreur survient lors de la saisie des données, comment puis-je identifier la raison de l'erreur de l'exception?
Si vous attrapez SqlException alors voyez son numéro, le nombre 2627
signifierait une violation de la contrainte unique (y compris la clé primaire).
try
{
// insertion code
}
catch (SqlException ex)
{
if (ex.Number == 2627)
{
//Violation of primary key. Handle Exception
}
else throw;
}
Il s’agit d’une erreur générale qui peut être générée indépendamment du fait que la base de données est répliquée. Dans les bases de données répliquées, l'erreur est généralement généré parce que les clés primaires n'ont pas été gérées correctement dans la topologie.
C'est un vieux fil, mais je suppose qu'il est important de noter que depuis le C # 6, vous pouvez:
try
{
await command.ExecuteNonQueryAsync(cancellation);
}
catch (SqlException ex) when (ex.Number == 2627)
{
// Handle unique key violation
}
Et avec C # 7 et une exception d'encapsulation (comme Entity Framework Core):
try
{
await _context.SaveChangesAsync(cancellation);
}
catch (DbUpdateException ex)
when ((ex.InnerException as SqlException)?.Number == 2627)
{
// Handle unique key violation
}
Le principal avantage de cette approche par rapport à la réponse acceptée est:
Si le numéro d'erreur est pas égal à 2627 et qu'il ne s'agit donc pas d'une violation de clé unique, l'exception n'est pas interceptée.
Sans le filtre d'exception (when
), vous feriez mieux de vous rappeler cette exception si vous ne pouvez pas la gérer. Et idéalement, n'oubliez pas d'utiliser ExceptionDispatchInfo
afin que la pile d'origine ne soit pas perdue.
Dans le cas d'Entity Framework, la réponse acceptée ne fonctionnera pas et l'erreur ne sera pas détectée. Voici un code de test, seule l'instruction d'entité de l'entité sera touchée ou bien sûr l'exception générique si l'instruction d'entité est supprimée:
try
{
db.InsertProcedureCall(id);
}
catch (SqlException e0)
{
// Won't catch
}
catch (EntityCommandExecutionException e1)
{
// Will catch
var se = e1.InnerException as SqlException;
var code = se.Number;
}
catch (Exception e2)
{
// if the Entity catch is removed, this will work too
var se = e2.InnerException as SqlException;
var code = se.Number;
}