public void Verify_that_2627_unique_constraint_is_parsed_correctly() { var message = "Violation of UNIQUE KEY constraint 'UQ_TableName_ColumnName'. Cannot insert duplicate key in object 'dbo.TableName'. The duplicate key value is (blablabla)."; var violation = SqlUniqueKeyViolation.Parse(SqlErrorCodes.UniqueConstraint, message); Assert.AreEqual("TableName", violation.TableName, "TableName incorrect."); Assert.AreEqual("ColumnName", violation.KeyName, "KeyName incorrect."); Assert.AreEqual("blablabla", violation.DuplicateKeyValue, "DuplicateKeyValue incorrect."); }
public void Verify_that_2601_unique_index_is_parsed_correctly() { var message = "Cannot insert duplicate key row in object 'dbo.TableName' with unique index 'IDX_TableName_ColumnName'. The duplicate key value is (blablabla)."; var violation = SqlUniqueKeyViolation.Parse(SqlErrorCodes.UniqueIndexConstraint, message); Assert.AreEqual("TableName", violation.TableName, "TableName incorrect."); Assert.AreEqual("ColumnName", violation.KeyName, "KeyName incorrect."); Assert.AreEqual("blablabla", violation.DuplicateKeyValue, "DuplicateKeyValue incorrect."); }
public void Verify_that_2601_unique_index_is_parsed_correctly_when_underscore_in_key_value() { var message = "Cannot insert duplicate key row in object 'dbo.TableName' with unique index 'idx_TableName_ColumnName'. The duplicate key value is (+«ÌSµ…p¹¸'Ä£M_t¥G)."; var violation = SqlUniqueKeyViolation.Parse(SqlErrorCodes.UniqueIndexConstraint, message); Assert.AreEqual("TableName", violation.TableName, "TableName incorrect."); Assert.AreEqual("ColumnName", violation.KeyName, "KeyName incorrect."); Assert.AreEqual("+«ÌSµ…p¹¸'Ä£M_t¥G", violation.DuplicateKeyValue, "DuplicateKeyValue incorrect."); }
/// <summary> /// Tries to execute the guarded code. /// </summary> /// <returns>The return value of type T, on success.</returns> /// <exception cref="ProviderInaccessibleException">On unknown errors and when the circuit continues to trip.</exception> /// <exception cref="DuplicateKeyException">When duplicate keys are detected.</exception> /// <exception cref="DataUpdatedException">When an optimistic concurrency conflict is detected.</exception> /// <exception cref="ErrorHandling.TimeoutException">When an action timed out.</exception> /// <exception cref="DeadlockedException">When a deadlock is detected.</exception> /// <remarks>Only two exceptions need to be catched: ProviderInaccessibleException and RecoverableException, since /// DuplicateKeyException, DataUpdatedException, TimeoutException and DeadlockedException all inherit from /// RecoverableException.</remarks> public async Task <TReturn> Execute() { var coolOffPeriod = retrySettings.CoolOffPeriod; int tryNumber = 0; Func <bool> retryThresholdReached = () => tryNumber >= retrySettings.RetryCount; var exceptionsCaught = new List <Exception>(); while (!retryThresholdReached()) { tryNumber++; try { return(await awaitableAction()); } catch (InvalidOperationException exception) { // InvalidOperationException most likely suggests that we tried to execute // when the curcuit breaker was in an invalid state. exceptionsCaught.Add(exception); if (retryThresholdReached()) { throw new ProviderInaccessibleException(exceptionsCaught); } } catch (SqlException sqlException) { if (sqlException.Number == SqlErrorCodes.ForeignKeyConstraint) { // This is an error, which is not recoverable here, so throw a new exception instead of retrying. var violation = SqlForeignKeyViolation.Parse(sqlException.Number, sqlException.Message); throw new ForeignKeyException(violation.LocalTable, violation.ForeignTable, violation.ForeignColumn, sqlException.Message, sqlException); } if (sqlException.Number == SqlErrorCodes.UniqueConstraint || sqlException.Number == SqlErrorCodes.UniqueIndexConstraint) { // This is a duplicate key error, which is not recoverable here, so throw a new exception instead of retrying. var violation = SqlUniqueKeyViolation.Parse(sqlException.Number, sqlException.Message); throw new DuplicateKeyException(violation.TableName, violation.KeyName, violation.DuplicateKeyValue, sqlException.Message, sqlException); } if (sqlException.Number == SqlErrorCodes.Deadlock) { // This is an error, which may be recoverable, so only throw if no more retries are left. if (retryThresholdReached()) { throw new DeadlockedException(sqlException); } } if (sqlException.Number == SqlErrorCodes.Timeout) { // This is an error, which may be recoverable, so only throw if no more retries are left. if (retryThresholdReached()) { throw new TimeoutException(sqlException); } } if (sqlException.Number == SqlErrorCodes.StringOrBinaryDataTruncation) { throw new TruncatedDataException("Data truncated.", sqlException); } if (retryThresholdReached()) { // Something is seriously wrong when we get to here. It is not recoverable. throw new ProviderInaccessibleException(sqlException); } } catch (TransactionAbortedException exception) { exceptionsCaught.Add(exception); // Something is seriously wrong when we get this exception. It is not recoverable. throw new ProviderInaccessibleException(methodDescriptor(), exceptionsCaught); } catch (Exception exception) { exceptionsCaught.Add(exception); // A generic exception may come from the guarded code. But since we have no idea what went // wrong, we must assume that the error is not recoverable. throw new ProviderInaccessibleException(methodDescriptor(), exceptionsCaught); } await Task.Delay(retrySettings.CoolOffPeriod); } // We have exceeded the retryCount so report that we cannot access the provider throw new ProviderInaccessibleException("Retry count exceeded. " + methodDescriptor(), exceptionsCaught); }