2009-09-23 3 views
14

Ho un DB SQL 2008. Sto facendo funzionare una forma che sostiene quel DB in su, quindi prova ad aggiornarlo. Se l'aggiornamento fallisce l'idea è di ripristinare quel backup. Ecco il codice che sto usando per ripristinare il backup.Come ripristinare un database da C#

public void RestoreDatabase(String databaseName, String backUpFile, String serverName, String userName, String password) 
{ 
    Restore sqlRestore = new Restore(); 
    BackupDeviceItem deviceItem = new BackupDeviceItem(backUpFile, DeviceType.File); 
    sqlRestore.Devices.Add(deviceItem); 
    sqlRestore.Database = databaseName; 
    ServerConnection connection = new ServerConnection(serverName, userName, password); 
    Server sqlServer = new Server(connection); 
    sqlRestore.Action = RestoreActionType.Database; 

    string logFile = System.IO.Path.GetDirectoryName(backUpFile); 
    logFile = System.IO.Path.Combine(logFile, databaseName + "_Log.ldf"); 

    string dataFile = System.IO.Path.GetDirectoryName(backUpFile); 
    dataFile = System.IO.Path.Combine(dataFile, databaseName + ".mdf"); 

    Database db = sqlServer.Databases[databaseName]; 
    RelocateFile rf = new RelocateFile(databaseName, dataFile); 
    sqlRestore.RelocateFiles.Add(new RelocateFile(databaseName, dataFile)); 
    sqlRestore.RelocateFiles.Add(new RelocateFile(databaseName + "_log", logFile)); 
    sqlRestore.SqlRestore(sqlServer); 
    db = sqlServer.Databases[databaseName]; 
    db.SetOnline(); 
    sqlServer.Refresh(); 
} 

il problema sembra essere il fatto che i nomi dei file che scelgo sono diverse da DB online. Fondamentalmente voglio sostituire il database sul server con il backup. Ricevo un'eccezione quando chiamo SqlRestore.

La principale eccezione dice

{ "Ripristino non riuscito per Server 'localhost'."}

Scavando nelle eccezioni interne mostra questi errori

verificata un'eccezione durante l'esecuzione di un'istruzione o batch Transact-SQL.

e poi

di file logico 'DB' non fa parte della database 'DB'. Utilizzare RESTORE FILELISTONLY per elencare il file logico nomi. \ R \ nRESTORE DATABASE è terminato in modo anomalo.

Suppongo che ci sia un modo per dire questo per usare solo sostituire il DB esistente così com'è.

Uso questo bit di codice per ottenere il percorso del file del DB in modo che una directory esegua il dump del backup. Forse questo potrebbe essere usato per far ricreare i nomi dei file.

public string GetDBFilePath(String databaseName, String userName, String password, String serverName) 
{ 
    ServerConnection connection = new ServerConnection(serverName, userName, password); 
    Server sqlServer = new Server(connection); 
    Database db = sqlServer.Databases[databaseName]; 
    return sqlServer.Databases[databaseName].PrimaryFilePath; 
} 

risposta

18

ho cambiato il mio back up e ripristinare le funzioni di simile a questa:

public void BackupDatabase(SqlConnectionStringBuilder csb, string destinationPath) 
{ 
    ServerConnection connection = new ServerConnection(csb.DataSource, csb.UserID, csb.Password); 
    Server sqlServer = new Server(connection); 

    Backup bkpDatabase = new Backup(); 
    bkpDatabase.Action = BackupActionType.Database; 
    bkpDatabase.Database = csb.InitialCatalog; 
    BackupDeviceItem bkpDevice = new BackupDeviceItem(destinationPath, DeviceType.File); 
    bkpDatabase.Devices.Add(bkpDevice); 
    bkpDatabase.SqlBackup(sqlServer); 
    connection.Disconnect(); 

} 

public void RestoreDatabase(String databaseName, String backUpFile, String serverName, String userName, String password) 
{ 
    ServerConnection connection = new ServerConnection(serverName, userName, password); 
    Server sqlServer = new Server(connection); 
    Restore rstDatabase = new Restore(); 
    rstDatabase.Action = RestoreActionType.Database; 
    rstDatabase.Database = databaseName; 
    BackupDeviceItem bkpDevice = new BackupDeviceItem(backUpFile, DeviceType.File); 
    rstDatabase.Devices.Add(bkpDevice); 
    rstDatabase.ReplaceDatabase = true; 
    rstDatabase.SqlRestore(sqlServer); 
} 

In questo modo essi basta usare qualunque file ci sono. Non ci sono più e le direttive per spostare i file.

+3

Non è necessario spostare i file se si ripristina da un backup dello stesso db sullo stesso computer.Il riposizionamento è necessario solo quando si spostano e si copiano i database tramite backup/ripristino. –

+3

Ok, ecco alcuni suggerimenti: per quanto riguarda il percorso del file di backup prestare sempre attenzione se il file esiste realmente nella cartella di origine. Per quanto riguarda il trasferimento, potrebbe essere un problema di autorizzazione scrivere file mdf. Prestare attenzione se la propria app ha il permesso di leggere il file .bak, in questo caso controllare il gestore della configurazione SQL: il servizio MSSQLServer deve essere in esecuzione con l'utente LocalSystem. –

4

Si sta aggiungendo RelocateFile opzioni in base al nome del database, che non è corretto. È necessario aggiungerli in base al nome file logico per ogni file spostato. Utilizzare Restore.ReadFileList per recuperare l'elenco dei nomi di file logici.

+0

Sembra che non possa aggiungere tutte queste opzioni tutte insieme. –

12

Grazie Remus per la tua risposta!

Ho modificato

sqlRestore.RelocateFiles.Add(new RelocateFile(databaseName, dataFileLocation)); 
sqlRestore.RelocateFiles.Add(new RelocateFile(databaseName + "_log", logFileLocation)); 

queste due righe per

System.Data.DataTable logicalRestoreFiles = sqlRestore.ReadFileList(sqlServer); 
sqlRestore.RelocateFiles.Add(new RelocateFile(logicalRestoreFiles.Rows[0][0].ToString(), dataFileLocation)); 
sqlRestore.RelocateFiles.Add(new RelocateFile(logicalRestoreFiles.Rows[1][0].ToString(), logFileLocation)); 

e il mio codice viene eseguito con successo.

Grazie per il supporto!

+0

@Pallavi La tua soluzione ha funzionato subito per me .. Ma non riesco a capire la soluzione, ti prego di riassumere la tua risposta alla soluzione. –

+1

Questa soluzione è stata perfetta anche per me. Per coloro che vogliono di più, ciò che detiene LocalRestoreFiles è il database di origine "Elenco file". L'elenco di file di quel database come tutti i file MDF, log e di indice che sono stati creati. Tuttavia, questi numeri di righe [X] presuppongono un DB normale con solo 1 MDF e 1 LDF (ad esempio nessun registro o file indice aggiuntivi). In questo caso, Rows [0] contiene il primo file MDF, Rows [1] sarà il file di registro. E Righe [0] [0] e Righe [1] [0] conterranno il nome del database logico (che è case sensitive!) Che puoi usare per "spostare". – eduncan911