Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
gäller för:SQL Server
Om en transaktion är aktiv vid den tidpunkt då CLR-kod (Common Language Runtime) som körs på SQL Server anges, exponeras transaktionen via klassen System.Transactions.Transaction. Egenskapen Transaction.Current används för att komma åt den aktuella transaktionen. I de flesta fall är det inte nödvändigt att uttryckligen komma åt transaktionen. För databasanslutningar kontrollerar ADO.NET Transaction.Current automatiskt när Connection.Open-metoden anropas och anger transparent anslutningen i transaktionen (såvida inte nyckelordet Enlist är inställt på false i anslutningssträngen).
Du kanske vill använda Transaction-objektet direkt i följande scenarier:
Om du vill registrera en resurs som inte gör automatisk registrering eller som av någon anledning inte har registrerats under initieringen.
Om du uttryckligen vill registrera en resurs i transaktionen.
Om du vill avsluta den externa transaktionen inifrån den lagrade proceduren eller funktionen. I det här fallet använder du TransactionScope. Följande kod återställer till exempel den aktuella transaktionen:
using(TransactionScope transactionScope = new TransactionScope(TransactionScopeOptions.Required)) { }
I resten av den här artikeln beskrivs andra sätt att avbryta en extern transaktion.
Avbryta en extern transaktion
Du kan avbryta externa transaktioner från en hanterad procedur eller funktion på följande sätt:
Den hanterade proceduren eller funktionen kan returnera ett värde med hjälp av en utdataparameter. Den anropande Transact-SQL-proceduren kan kontrollera det returnerade värdet och, om det är lämpligt, köra
ROLLBACK TRANSACTION.Den hanterade proceduren eller funktionen kan utlösa ett anpassat undantag. Den anropande Transact-SQL-proceduren kan fånga undantaget som genereras av den hanterade proceduren eller funktionen i ett try/catch-block och köra
ROLLBACK TRANSACTION.Den hanterade proceduren eller funktionen kan avbryta den aktuella transaktionen genom att anropa metoden
Transaction.Rollbackom ett visst villkor uppfylls.
När metoden Transaction.Rollback anropas inom en hanterad procedur eller funktion utlöser den ett undantag med ett tvetydigt felmeddelande och kan omslutas i ett try/catch-block. Felmeddelandet liknar följande utdata:
Msg 3994, Level 16, State 1, Procedure uspRollbackFromProc, Line 0
Transaction is not allowed to roll back inside a user defined routine, trigger or aggregate because the transaction is not started in that CLR level. Change application logic to enforce strict transaction nesting.
Det här undantaget förväntas och try/catch-blocket är nödvändigt för att kodkörningen ska fortsätta. Utan try/catch-blocket utlöses undantaget omedelbart till den anropande Transact-SQL-proceduren och körningen av hanterad kod slutförs. När den hanterade koden har slutfört körningen utlöses ett annat undantag:
Msg 3991, Level 16, State 1, Procedure uspRollbackFromProc, Line 1
The context transaction which was active before entering user defined routine, trigger or aggregate " uspRollbackFromProc " has been ended inside of it, which is not allowed. Change application logic to enforce strict transaction nesting. The statement has been terminated.
Det här undantaget förväntas också, och för att körningen ska fortsätta måste du ha ett try/catch-block runt Transact-SQL-instruktionen som utför åtgärden som utlöser utlösaren. Trots de två undantagen återställs transaktionen och ändringarna bekräftas inte.
Exempel
Följande kod är ett exempel på en transaktion som återställs från en hanterad procedur med hjälp av metoden Transaction.Rollback. Observera try/catch-blocket runt metoden Transaction.Rollback i den hanterade koden. Skriptet Transact-SQL skapar en sammansättning och en hanterad lagrad procedur.
EXEC uspRollbackFromProc-instruktionen omsluts i ett try/catch-block, så att undantaget som utlöses när den hanterade proceduren slutför körningen fångas.
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Transactions;
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void uspRollbackFromProc()
{
using (SqlConnection connection = new SqlConnection(@"context connection=true"))
{
// Open the connection.
connection.Open();
bool successCondition = true;
// Success condition is met.
if (successCondition)
{
SqlContext.Pipe.Send("Success condition met in procedure.");
// Perform other actions here.
}
// Success condition is not met, the transaction will be rolled back.
else
{
SqlContext.Pipe.Send("Success condition not met in managed procedure. Transaction rolling back...");
try
{
// Get the current transaction and roll it back.
Transaction trans = Transaction.Current;
trans.Rollback();
}
catch (SqlException ex)
{
// Catch the expected exception.
// This allows the connection to close correctly.
}
}
// Close the connection.
connection.Close();
}
}
};
Registrera och köra sammansättningen i Transact-SQL
Registrera sammansättningen.
CREATE ASSEMBLY TestProcs FROM 'C:\Programming\TestProcs.dll'; GO CREATE PROCEDURE uspRollbackFromProc AS EXTERNAL NAME TestProcs.StoredProcedures.uspRollbackFromProc; GOKör proceduren.
BEGIN TRY BEGIN TRANSACTION; -- Perform other actions. EXECUTE uspRollbackFromProc; -- Perform other actions. PRINT N'Commiting transaction...'; COMMIT TRANSACTION; END TRY BEGIN CATCH SELECT ERROR_NUMBER() AS ErrorNum, ERROR_MESSAGE() AS ErrorMessage; PRINT N'Exception thrown, rolling back transaction.'; ROLLBACK; PRINT N'Transaction rolled back.'; END CATCH GORensa din miljö.
DROP PROCEDURE uspRollbackFromProc; GO DROP ASSEMBLY TestProcs; GO