2012-10-31 13 views
7

Attualmente sto cercando di eliminare un database tramite il seguente codiceaffidabile cadere un database in SQL Server 2008 tramite C#

using Microsoft.SqlServer.Management.Smo; 

var server = new Server(Server); 
server.KillAllProcesses("Db"); 
server.KillDatabase("Db"); 

a volte funziona, ma altri ottengo la seguente eccezione:

Microsoft.SqlServer.Management.Smo.FailedOperationException: Kill database non riuscito per Server 'Host1'.
---> Microsoft.SqlServer.Management.Common.ExecutionFailureException: si è verificata un'eccezione durante l'esecuzione di un'istruzione Transact-SQL o di un batch.
---> System.Data.SqlClient.SqlException: le modifiche allo stato o alle opzioni del database 'Db' non possono essere apportate in questo momento. Il database è in modalità utente singolo e un utente è attualmente collegato ad esso.

Qualche idea su come rilasciare il database in modo affidabile tramite codice?

+0

Hai provato ' ALTER DATABASE Db SET MULTI_USER ;, prima? –

+5

Personalmente non userò SMO per questo, principalmente perché non so esattamente cosa facciano quelle funzioni di 'Kill ...()'. Preferirei dire "USE master"; ALTER DATABASE Db SET SINGLE_USER CON ROLLBACK IMMEDIATO; DROP DATABASE Db; ' –

+0

Il database non è impostato come SingleUser per impostazione predefinita, penso che un tentativo fallito sul metodo KillDatabase lo trasformi in un singolo utente e lo lasci in quel modo. – Konstantinos

risposta

3

Per eliminare in modo affidabile il database tramite SMO è sufficiente chiamare server.KillDatabase("Db");. MSDN indica che KillDatabase rilascia connessioni attive anche se i loro esempi sono un po 'fuorvianti.

KillDatabase numeri ALTER DATABASE [Db] SET SINGLE_USER WITH ROLLBACK IMMEDIATE e quindi DROP DATABASE. KillAllProcesses elenca tutte le connessioni ed emette un kill per processo come batch separato; supponendo che KillAllProcesses sia asincrono, l'eccezione viene generata quando si verifica un'uccisione dopo che KillDatabase imposta il DB sulla modalità utente singolo.

1

Nel mio caso l'errore che stavo ottenendo è stato risolto aggiungendo server.Databases.Refresh prima del metodo KILL. Il motivo per cui il database che stavo cercando di eliminare è stato creato dopo che l'oggetto Server è stato istanziato, in altre parole stavo creando un database temporaneamente, estraendo i dati da esso e rilasciandolo. Il database non veniva visualizzato nell'elenco dei database (oggetto). Aggiunta di aggiornamento ha fatto il trucco ...

0

Ho risolto tale errore creando ServerConnection senza pool. Come questo:

var serverConnection = new ServerConnection(serverName) 
{ 
    ..., 
    NonPooledConnection = true 
}; 
server = new Server(serverConnection); 
server.KillAllProcesses(databaseName); 
1

ho ottenuto l'errore ("drop fallito ...") Utilizzando MSDN:

dbServer.KillAllProcesses(db.Name); 
dbServer.KillDatabase(db.Name); 

Il lavoro attorno era:

string sqlCommandText = @"USE master; 
ALTER DATABASE [" + db.Name + "] SET SINGLE_USER WITH ROLLBACK IMMEDIATE; 
DROP DATABASE [" + db.Name + "]"; 
dbServer.ConnectionContext.ExecuteNonQuery(sqlCommandText); 
Problemi correlati