Hubo una actualización masiva para manejar el error dentro de SQL Server 2005. Estos artículos son bastante extensa: Error Handling in SQL 2005 and Later by Erland Sommarskog y Error Handling in SQL 2000 – a Background by Erland Sommarskog
La mejor manera es algo como esto:
Crear el procedimiento almacenado como:
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
Sin embargo, eso es solo para SQL Server 2005 en adelante.Sin utilizar los bloques TRY-CATCH en SQL Server 2005, es muy difícil eliminar todos los mensajes que SQL Server envía de vuelta. El extra messages
que se refieren a son causados por la naturaleza de cómo se manejan usando reversiones @@ trancount:
de http://www.sommarskog.se/error-handling-I.html#trancount
@@ trancount es una variable global que refleja el nivel de transacciones anidadas . Cada BEGIN TRANSACTION aumenta @@ trancount por 1, y cada COMMIT TRANSACTION disminuye @@ trancount por 1. Nada es en realidad cometido hasta @@ trancount llega a 0. ROLLBACK TRANSACTION deshace todo a la más exterior COMENZAR TRANSACCIÓN (a menos que haya usado el TRANSACCIÓN DE AHORRO bastante exótica), y fuerza @@ trancount a 0, respetando el valor anterior.
Al salir de un procedimiento almacenado, si @@ trancount no tiene el mismo valor como lo había hecho cuando el procedimiento de ejecución comenzado, SQL Server genera el error 266. no se produce este error, sin embargo, si el procedimiento se llama desde un disparador, directamente o indirectamente. Tampoco se planteó si está ejecutando con set implícitos TRANSACCIONES EN
Si no desea conseguir la advertencia acerca de la transacción cuenta que no se ajuste, es necesario tener una sola transacción abierta en un momento dado . Esto se hace mediante la creación de la totalidad de su procedimiento de la siguiente manera:
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
De esta manera, sólo se emite los comandos de la transacción, si no está ya en una transacción. Si codifica todos sus procedimientos de esta manera, solo el procedimiento o el código C# que emite BEGIN TRANSACTION emitirá COMMIT/ROLLBACK y los recuentos de transacciones siempre coincidirán (no obtendrá un error).
en C# desde 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;
}
Es sólo una idea, pero es posible que pueda utilizar la captura TransactionAbortedException
para obtener el error real y hacer caso omiso de la advertencia desajuste número de transacciones.
@KM, tiene 'IF @@ trancount <0' al principio del proceso de muestra. ¿Puede @@transcount alguna vez ser negativo? No debería ser esto: 'IF @@ trancount = 0' ?? –
@Charles Bretana, tienes razón, es un tipo-o. Lo arreglaré ... –
@KM, Thx! funcionó en mi versión de prueba con el cambio, pero esto ha estado aquí desde abril/mayo ... Así que mi suposición natural es que me falta algo ... No estaba del todo seguro de una manera u otra ... Feliz ¡Vacaciones! –