2016-07-01 2 views
-1

J'exécute une procédure stockée sur une base de données via une application C#. Je voudrais faire des calculs après que la procédure stockée est exécutée et après que les calculs soient terminés, je voudrais retourner la base de données à son état avant la procédure stockée. La plupart des exemples que j'ai vus sur le débordement de pile impliquent seulement l'utilisation d'une restauration dans un bloc catch d'un bloc try/catch en cas d'erreur, mais c'est différent de ce que je fais. Je ne suis pas sûr si je devrais enregistrer l'état de la base de données à un moment donné, puis faire une annulation de transaction avec cet état, ou attacher un paramètre de transaction à l'instance SqlCommand de la procédure stockée, ou autre chose.Comment exécuter une procédure stockée et annuler les modifications ultérieurement?

Répondre

0

Vous pouvez le faire via des transactions. L'échantillon est ici: https://msdn.microsoft.com/en-us/library/86773566(v=vs.110).aspx Oui, il utilise également le bloc catch mais vous n'avez pas à le faire.

Vous pouvez également utiliser des instantanés de base de données si votre édition de SQL Server les prend en charge mais ils annuleront TOUS LES CHANGEMENTS DEPUIS QUE L'INSTANTANÉ DE MOMENT A ÉTÉ FAIT - le vôtre et n'importe quel autre utilisateur. Très probablement, ce n'est pas ce que vous voulez.

0

Une option consiste à utiliser un délai WAITFOR en combinaison avec un niveau d'isolement de transaction modifié. Ce que cela fait est d'exécuter votre code, fait attendre la requête pendant un certain laps de temps, puis annule la transaction. Pendant cette période, vous pouvez avoir une autre requête de session de votre table qui a reçu la modification (tant que vous avez défini le niveau de la transaction à lire non validée) et vous pourrez voir la nouvelle valeur. Voici un exemple:

Dans une fenêtre de SSMS:

CREATE TABLE ##testtable (id INT); 

BEGIN TRAN; 

INSERT INTO ##testtable (id) 
VALUES (1), (2), (3); 

WAITFOR DELAY '00:01:00'; 
ROLLBACK TRAN 

Dans une deuxième fenêtre SSMS, exécutez cette requête au cours de la période 1 minute:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 

SELECT * 

FROM ##testtable 

Pendant la 1 minute que la l'autre fenêtre est en cours d'exécution, vous verrez la valeur dans la table temporaire. Après une minute, la table sera vide. Cela fonctionne pour des tâches un peu simples, mais si vous effectuez un test sur des données pour lesquelles un test a déjà été modifié, effectuez simplement un instantané ou une restauration de base de données.

0

Avertissement: Ce n'est peut-être pas une bonne chose à faire. (OK, c'est fait.)

Vous pouvez le faire le plus facilement dans votre procédure stockée en utilisant un table variable. Vous pouvez

commencer une transaction
modifier vos données
requête les données modifiées
l'insérer dans la table des variables
rouleau la transaction
sélectionner ce qui est dans la table des variables

declare @myData table (someColumn int, someOtherColumn varchar(10)) 

begin transaction 

begin try 
    [make your changes] 

    insert into @myData 
    select something, something something 

    rollback transaction 

    select * from @myData 
end try 
begin catch 
    rollback transaction 
end catch 

roulant retour votre transaction n'affectera pas ce qui est dans la variable de table. Je ferais plus confiance à cela que de compter sur ma demande pour annuler la transaction. Ce n'est pas que ça ne marcherait pas, mais je ferais bien plus confiance. Cela étant dit, vous pouvez simplement créer un SqlTransaction (docs), exécuter votre SqlCommand en utilisant cette transaction, interroger vos données, puis annuler la transaction.