2009-09-23 10 views
14

Mam SQL 2008 DB. Uruchamiam formularz, który wykonuje kopię DB, a następnie próbuje ją zaktualizować. Jeśli aktualizacja się nie powiedzie, chodzi o przywrócenie tej kopii zapasowej. Oto kod, którego używam do przywrócenia kopii zapasowej.Jak przywrócić bazę danych z 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(); 
} 

Kwestia wydaje się, że wybrane przeze mnie nazwy różnią się od DB online. Zasadniczo chcę zastąpić bazę danych na serwerze kopią zapasową. Dostaję wyjątek, gdy zadzwonię do SqlRestore.

Głównym wyjątkiem mówi

{ "Przywracanie nie powiodło się dla serwera 'localhost'."}

Kopanie do wewnętrznej wyjątki przedstawiono te błędy

wystąpił wyjątek podczas wykonywania Transact-SQL lub partia.

a następnie

Logical plik 'DB' nie jest częścią bazy danych 'DB'. Użyj RESTORE FILELISTONLY, aby wyświetlić nazwy plików logicznych . \ R \ nRESTORE DATABASE to niepoprawnie.

Zakładam, że istnieje sposób, aby powiedzieć, aby po prostu użyć zastąpić istniejący DB, jak jest.

Używam tego fragmentu kodu, aby uzyskać ścieżkę do pliku bazy danych, aby mieć katalog do zrzutu kopii zapasowej. Może to może być użyte do uzyskania nazw plików do odtworzenia.

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; 
} 

Odpowiedz

18

zmieniłem kopię zapasową i przywrócić funkcje wyglądać następująco:

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); 
} 

w ten sposób po prostu użyć niezależnie pliki istnieją. Nie ma już i dyrektyw dotyczących przenoszenia plików.

+3

Nie musisz przenosić plików, jeśli przywrócisz kopię zapasową tej samej bazy danych na tym samym komputerze.Przeniesienie jest potrzebne tylko podczas przenoszenia i kopiowania baz danych poprzez tworzenie kopii zapasowych/przywracanie. –

+3

OK, oto kilka wskazówek: w odniesieniu do ścieżki pliku kopii zapasowej zawsze zwracaj uwagę, jeśli plik naprawdę istnieje w twoim folderze źródłowym. Jeśli chodzi o przenoszenie, może to być problem z uprawnieniami do zapisu pliku mdf. Zwróć uwagę, czy Twoja aplikacja ma uprawnienia do odczytu pliku .bak, w tym przypadku sprawdź Menedżera konfiguracji SQL: Usługa MSSQLServer musi działać pod kontrolą użytkownika LocalSystem. –

4

możliwość dodawania RelocateFile opcje na podstawie nazwy bazy danych, które są nieprawidłowe. Powinieneś dodać je na podstawie logicznej nazwy pliku dla każdego przeniesionego pliku. Użyj Restore.ReadFileList, aby pobrać listę logicznych nazw plików.

+0

Wygląda na to, że nie mogę po prostu dodać tych opcji razem. –

12

Dziękuję Remus za odpowiedź!

Mam zmodyfikowany

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

te dwie linie do

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)); 

i mój kod działa poprawnie.

Dzięki za wsparcie!

+0

@Pallavi Twoje rozwiązanie zadziałało od razu dla mnie .. Ale nie mogę zrozumieć rozwiązania, Czy podoba Ci się odpowiedź na rozwiązanie? –

+1

To rozwiązanie również było dla mnie idealne. Dla tych, którzy chcą więcej, jakie pliki localRestoreFiles przechowuje są źródłowe bazy danych "Lista plików". Lista plików tej bazy danych, takich jak wszystkie utworzone pliki MDF, dzienniki i indeksy. Ale te numery wierszy [X] zakładają, że masz normalny DB z tylko 1 MDF i 1 LDF (np. Bez dodatkowych dzienników lub plików indeksu). Jeśli tak jest, wiersze [0] zawierają pierwszy plik MDF, wiersze [1] będą plikiem dziennika. A wiersze [0] [0] i wiersze [1] [0] będą zawierały logiczną nazwę bazy danych (to jest w sensie!), Której możesz użyć do "przeniesienia". – eduncan911

Powiązane problemy