Il y avait une mise à jour massive à l'erreur de manipulation dans SQL Server 2005. Ces articles sont assez nombreuses: Error Handling in SQL 2005 and Later by Erland Sommarskog et Error Handling in SQL 2000 – a Background by Erland Sommarskog
La meilleure façon est quelque chose comme ceci:
Créer votre procédure stockée comme:
CREATE PROCEDURE YourProcedure
AS
BEGIN TRY
BEGIN TRANSACTION --SqlTransaction
DECLARE @ReturnValue int
SET @ReturnValue=NULL
IF (DAY(GETDATE())=1 --logical error
BEGIN
SET @ReturnValue=5
RAISERROR('Error, first day of the month!',16,1) --send control to the BEGIN CATCH block
END
SELECT 1/0 --actual hard error
COMMIT TRANSACTION --SqlTransaction
RETURN 0
END TRY
BEGIN CATCH
IF XACT_STATE()!=0
BEGIN
ROLLBACK TRANSACTION --only rollback if a transaction is in progress
END
--will echo back the complete original error message to the caller
--comment out if not needed
DECLARE @ErrorMessage nvarchar(400), @ErrorNumber int, @ErrorSeverity int, @ErrorState int, @ErrorLine int
SELECT @ErrorMessage = N'Error %d, Line %d, Message: '+ERROR_MESSAGE(),@ErrorNumber = ERROR_NUMBER(),@ErrorSeverity = ERROR_SEVERITY(),@ErrorState = ERROR_STATE(),@ErrorLine = ERROR_LINE()
RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState, @ErrorNumber,@ErrorLine)
RETURN ISNULL(@ReturnValue,1)
END CATCH
GO
Toutefois, ce n'est que pour SQL Server 2005 et versions ultérieures.Sans utiliser les blocs TRY-CATCH dans SQL Server 2005, vous avez du mal à supprimer tous les messages que SQL Server renvoie. Le extra messages
vous renvoie à sont causés par la nature de la façon dont sont traitées à l'aide rollbacks @@ trancount:
de http://www.sommarskog.se/error-handling-I.html#trancount
@@ trancount est une variable globale qui reflète le niveau de transactions imbriquées. Chaque BEGIN TRANSACTION augmente @@ trancount par 1, et chaque COMMIT TRANSACTION diminue @@ trancount par 1. Rien n'est en fait commis jusqu'à ce que @@ trancount atteint 0. ROLLBACK TRANSACTION annule tout au plus à l'extérieur BEGIN TRANSACTION (sauf si vous avez utilisé le assez exotique SAVE TRANSACTION), et force @@ trancount à 0, en ce qui concerne la valeur précédente.
Lorsque vous quittez une procédure stockée, si @@ trancount n'a pas la même valeur telle qu'elle avait lorsque la procédure d'exécution commencé, SQL Server génère erreur 266. Cette erreur ne se pose pas, cependant, si la procédure est appelée à partir d'un déclencheur, directement ou indirectement. Il n'est pas élevé si vous utilisez avec SET IMPLICIT TRANSACTIONS SUR
Si vous ne voulez pas obtenir l'avertissement au sujet de la transaction ne correspond pas à compter, vous devez avoir seulement une transaction ouverte à tout moment . Vous faites cela en créant toute votre procédure comme ceci:
CREATE PROC YourProcedure
AS
DECLARE @SelfTransaction char(1)
SET @SelfTransaction='N'
IF @@trancount=0
BEGIN
SET @SelfTransaction='Y'
BEGIN TRANSACTION --SqlTransaction
END
SELECT 1/0
IF @@ERROR<> 0
BEGIN
IF @SelfTransaction='Y'
BEGIN
ROLLBACK TRANSACTION --SqlTransaction
END
RETURN -1
END
ELSE
BEGIN
IF @SelfTransaction='Y'
BEGIN
COMMIT TRANSACTION --SqlTransaction
END
RETURN 0
END
GO
En faisant cela, vous émettez que la transaction commandes si vous n'êtes pas déjà dans une transaction. Si vous codez toutes vos procédures de cette façon, seule la procédure ou le code C# qui émet BEGIN TRANSACTION lancera le COMMIT/ROLLBACK et le nombre de transactions correspondra toujours (vous n'obtiendrez pas d'erreur).
en C# de TransactionScope Class Documentation:
static public int CreateTransactionScope(
string connectString1, string connectString2,
string commandText1, string commandText2)
{
// Initialize the return value to zero and create a StringWriter to display results.
int returnValue = 0;
System.IO.StringWriter writer = new System.IO.StringWriter();
try
{
// Create the TransactionScope to execute the commands, guaranteeing
// that both commands can commit or roll back as a single unit of work.
using (TransactionScope scope = new TransactionScope())
{
using (SqlConnection connection1 = new SqlConnection(connectString1))
{
// Opening the connection automatically enlists it in the
// TransactionScope as a lightweight transaction.
connection1.Open();
// Create the SqlCommand object and execute the first command.
SqlCommand command1 = new SqlCommand(commandText1, connection1);
returnValue = command1.ExecuteNonQuery();
writer.WriteLine("Rows to be affected by command1: {0}", returnValue);
// If you get here, this means that command1 succeeded. By nesting
// the using block for connection2 inside that of connection1, you
// conserve server and network resources as connection2 is opened
// only when there is a chance that the transaction can commit.
using (SqlConnection connection2 = new SqlConnection(connectString2))
{
// The transaction is escalated to a full distributed
// transaction when connection2 is opened.
connection2.Open();
// Execute the second command in the second database.
returnValue = 0;
SqlCommand command2 = new SqlCommand(commandText2, connection2);
returnValue = command2.ExecuteNonQuery();
writer.WriteLine("Rows to be affected by command2: {0}", returnValue);
}
}
// The Complete method commits the transaction. If an exception has been thrown,
// Complete is not called and the transaction is rolled back.
scope.Complete();
}
}
catch (TransactionAbortedException ex)
{
writer.WriteLine("TransactionAbortedException Message: {0}", ex.Message);
}
catch (ApplicationException ex)
{
writer.WriteLine("ApplicationException Message: {0}", ex.Message);
}
// Display messages.
Console.WriteLine(writer.ToString());
return returnValue;
}
Juste une pensée, mais vous pourriez être en mesure d'utiliser les TransactionAbortedException
prises pour obtenir l'erreur réelle et ignorer le nombre de transactions d'avertissement de non-concordance.
@KM, Vous avez 'IF @@ trancount <0' tôt dans l'exemple de proc. Est-ce que @@ trancount peut être négatif? Ne devrait-il pas être IF @@ trancount = 0' ?? –
@Charles Bretana, vous avez raison, c'est un type-o. Je vais le réparer ... –
@KM, Thx! ça a fonctionné dans mon test sproc avec le changement, mais ça a été ici non perturbé depuis avril/mai ... Donc mon hypothèse naturelle est qu'il me manque quelque chose ... je n'étais pas complètement sûr d'une façon ou d'une autre ... Heureux Vacances ! –