2013-05-16 8 views
10

Supponiamo di utilizzare C# per eseguire una stored procedure SQL Server di lunga durata (diciamo 30 minuti). Supponiamo inoltre di mettere un intervallo di timeout di 1 ora sulla query in C# in modo tale che se per qualsiasi ragione questo SP impieghi più tempo del previsto, non finirò per monopolizzare il DB. Supponiamo infine che questa procedura memorizzata contenga un blocco try/catch per rilevare gli errori e fare un po 'di pulizia nel caso in cui eventuali passaggi interni non riescano.Che cosa fa SQL Server con una richiesta scaduta?

Alcuni di codice (C#):

using (SqlCommand comm = new SqlCommand("longrunningstoredproc")) 
{ 
    comm.Connection = conn; 
    comm.CommandType = CommandType.StoredProcedure; 
    comm.CommandTimeout = 3600; 
    comm.ExecuteNonQuery(); 
} 
/* Note: no transaction is used here, the transactions are inside the stored proc itself. */ 

T-SQL (in pratica equivale al seguente):

BEGIN TRY 
    -- initiailize by inserting some rows into a working table somewhere 
    BEGIN TRANS 
    -- do long running work 
    COMMIT TRANS 
    BEGIN TRANS 
    -- do long running work 
    COMMIT TRANS 
    BEGIN TRANS 
    -- do long running work 
    COMMIT TRANS 
    BEGIN TRANS 
    -- do long running work 
    COMMIT TRANS 
    BEGIN TRANS 
    -- do long running work 
    COMMIT TRANS 
    -- etc. 

    -- remove the rows from the working table (and set another data point to success) 
END TRY 
BEGIN CATCH 
    -- remove the rows from the working table (but don't set the other data point to success) 
END CATCH 

La mia domanda è, quale sarà SQL Server fare con la query quando il comando va fuori tempo dal lato C#? Richiama il blocco catch del SP, o lo interromperà del tutto in modo tale che avrei bisogno di eseguire il clean-up nel codice C#?

+0

Il comando non verrà timeout dal sito # C - il database sarà tempo fuori. Il codice C# non ha alcun controllo su questo (ha detto al DB di scadere dopo 1 ora, e il DB fa proprio questo). – Oded

risposta

5

Il timeout viene applicato da ADO.NET. SQL Server non conosce un timeout di comando. Il client .NET invierà un comando TDS "attenzione". È possibile osservare questo comportamento con SQL Profiler perché ha un evento di "attenzione".

Quando SQL Server riceve l'annullamento, annulla la query attualmente in esecuzione (proprio come fa SSMS quando si preme il pulsante di arresto). Annullerà il batch (proprio come in SSMS). Ciò significa che nessun codice di cattura può essere eseguito. La connessione rimarrà in vita.

In base alla mia esperienza, la transazione verrà annullata immediatamente. Non penso che questo sia comunque garantito.

TL; DR: un timeout in ADO.NET si comporta come se fosse stato premuto Stop in SSMS (o chiamato SqlCommand.Cancel).

Ecco riferimento per questo: http://blogs.msdn.com/b/psssql/archive/2008/07/23/how-it-works-attention-attention-or-should-i-say-cancel-the-query-and-be-sure-to-process-your-results.aspx

3

Il timeout è qualcosa che si verifica sulla connessione, non sulla query in esecuzione.

Ciò significa che il tuo BEGIN CATCH non verrà eseguito in caso di un timeout, in quanto la query non ne ha idea.

Scrivi la pulizia in C#, in un blocco catch(SqlException ex) (test per un timeout).