2011-11-30 10 views
5

Ho un'app utilizzata per la gestione dei database per le demo del nostro software, una delle cose che fa è ottenere una copia di un database da un server centrale e ripristinare a un'istanza SQL locale. Tutto funziona correttamente sulla porzione di backup ma sul ripristino alcune persone stanno segnalando che ottengono la seguente eccezione nel mezzo del ripristino.SMO.Restore.SqlRestore a volte genera un'eccezione di timeout sui computer distribuiti

Microsoft.SqlServer.Management.Smo.FailedOperationException: Restore failed for Server 'Computername'. 
---> Microsoft.SqlServer.Management.Common.ExecutionFailureException: 
    An exception occurred while executing a Transact-SQL statement or batch. 
    ---> System.Data.SqlClient.SqlException: Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. 
      at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) 
      (snip) 
      at Microsoft.SqlServer.Management.Common.ServerConnection.ExecuteNonQuery(String sqlCommand, ExecutionTypes executionType) 
     --- End of inner exception stack trace --- 
     at Microsoft.SqlServer.Management.Common.ServerConnection.ExecuteNonQuery(String sqlCommand, ExecutionTypes executionType) 
     (snip) 
     at Microsoft.SqlServer.Management.Smo.Restore.SqlRestore(Server srv) 
--- End of inner exception stack trace --- 
at Microsoft.SqlServer.Management.Smo.Restore.SqlRestore(Server srv) 
at ContractFlowTool.WebInfinity2.AttachDatabase.RestoreLocal(AttachDatabaseArgs arg) 

La MSDN is fairly light sul funzionamento interno delle classi SMO. Non sono riuscito a trovare alcun metodo per modificare il tempo di timeout per l'esecuzione del ripristino. Cosa posso fare in modo che l'eccezione non accada?


ecco il codice che esegue il ripristino

private static bool RestoreLocal(AttachDatabaseArgs arg) 
{ 
    if (arg.DestDatabase == null) 
     throw new ArgumentNullException("DestDatabase"); 
    SqlConnectionInfo serverConnInfo = new SqlConnectionInfo(/*snip*/); 
    ServerConnection serverConn = null; 
    serverConn = new ServerConnection(serverConnInfo); 
    var remoteServer = new Server(serverConn); 
    var clinicFolder = ClinicFolder(arg); 
    var restore = new Restore(); 
    restore.PercentCompleteNotification = 5; 
    restore.NoRecovery = false; 
    restore.RelocateFiles.Add(/*snip mdf*/); 
    restore.RelocateFiles.Add(/*snip ldf*/); 
    restore.Database = arg.LocalDB; 
    restore.ReplaceDatabase = true; 
    restore.Action = RestoreActionType.Database; 
    restore.PercentComplete += arg.ProgressForm.Restore_PercentComplete; 

    restore.SqlRestore(remoteServer); 
} 
+0

Can si reprod questo lo fai personalmente? La dimensione del database è un fattore? Ci sono campi binari davvero enormi che potrebbero causare questo? Il timeout si verifica dopo un intervallo di tempo consistente? Se sei davvero bloccato, potresti avere un po 'di fortuna a scavare negli assiemi usando Reflector per vedere come funzionano (e replicandolo, probabilmente attraverso la riflessione (per ottenere membri privati ​​/ interni), con un timeout più alto). Hai visto [questo] (http://stackoverflow.com/q/5979086/21475)? – Cameron

risposta

8

Grazie al Camerons suggestione la soluzione a questo problema è stato che ho bisogno di impostare ServerConnection.StatementTimeout più alto. Apparentemente ciò accade frequentemente quando i database sono più grandi di 3 GB.

(...) 
serverConn = new ServerConnection(serverConnInfo); 
serverConn.StatementTimeout = 240; //<- set this. 
var remoteServer = new Server(serverConn); 
var clinicFolder = ClinicFolder(arg); 
(...) 
0

u potrebbe utilizzare questo, specialmente quando non è possibile modificare stringa di connessione o la modifica dei timeout in stringa di connessione non funziona Funziona per me per un database con mirroring più di 2 GB

Utilizzando (SqlConnection1)

Dim sqlStmt come stringa = String.Format ("database cartografico backup su disco = '{0}'", backup_directory + backupfile)

  Using bu2 As New SqlCommand(sqlStmt, SqlConnection1) 
       SqlConnection1.Open() 
       bu2.CommandTimeout = 180 //this line is the key 
       bu2.ExecuteNonQuery() 
       SqlConnection1.Close() 
      End Using 
     End Using 
+1

Sì, StatementTimeout esegue il mapping a CommandTimeout, tuttavia questa domanda riguardava l'utilizzo di SMO non SqlCommand –