2013-01-17 27 views
12

Używam serwera SMO serwera SQL do przywrócenia pliku .bak do nowej bazy danych, ale nie działa.Baza danych odtwarzania smo

serwer SQL jest 2012 i SMO wersja obiektu jest z najnowszej wersji sdk 11,0

plik .bak został utworzony za pomocą SQL Management Studio 2012, tego samego lokalnego komputera, na tym samym komputerze, a także kodowania.

Komunikat o błędzie pojawia się:

Przywracanie nie powiodło się dla serwera 'serwera.

Co jest nie tak z moim kodem?

string dbPath = Path.Combine(@"d:\my data", dbName + "_db" + ".mdf"); 
string logPath = Path.Combine(@"d:\my data", dbName + "_db" + "_Log.ldf"); 

Restore restore = new Restore(); 

BackupDeviceItem deviceItem = new BackupDeviceItem("d:\template.BAK", DeviceType.File); 
restore.Devices.Add(deviceItem); 
restore.Database = dbName + "_db"; 

RelocateFile relocateDataFile = new RelocateFile("Data", dbPath); 
RelocateFile relocateLogFile = new RelocateFile("Log", logPath); 

restore.RelocateFiles.Add(relocateDataFile); 
restore.RelocateFiles.Add(relocateLogFile); 

restore.Action = RestoreActionType.Database; 
restore.ReplaceDatabase = true; 
restore.SqlRestore(server); 

AKTUALIZACJA: I poddał rozwiązań SMO i spróbował

using (SqlConnection connection = new SqlConnection("Data Source=server;user id=sa;password=xxxxx;")) 
     { 

      using (SqlCommand command = new SqlCommand(@"RESTORE DATABASE beauty01 FROM DISK = 'd:\template.bak' WITH RECOVERY, MOVE 'beauty1' TO 'D:\MyData\beauty01_Data.mdf', MOVE 'beauty1_log' TO 'd:\Mydata\beauty01_Log.ldf', REPLACE", connection)) 
      { 
       connection.Open(); 
       // Add the parameters for the SelectCommand. 


       command.CommandType = CommandType.Text; 
       command.ExecuteNonQuery(); 
      } 

     } >> work good. 

Dzięki wszystkim.

+0

Czy istnieje wyjątek wewnętrzny? Sprawdź debugowanie, które prawdopodobnie da ci prawdziwy powód. – Bridge

+0

Czy na pewno nie próbujesz zastąpić istniejących już plików? Jeśli używasz tej samej nazwy dbName, możesz mieć dane i pliki dziennika o tej samej nazwie - spróbuj sprawdzić, czy plik istnieje najpierw, a jeśli tak, nie próbuj tworzyć go ponownie. – Bridge

+0

Nie można otworzyć urządzenia kopii zapasowej "d: \ template.BAK". Błąd systemu operacyjnego 123 (Nazwa pliku, nazwa katalogu lub składnia etykiety woluminu jest niepoprawna). >> .bak został stworzony przez sql management studio 2012 i smo jest poprawną wersją (wersja 11). –

Odpowiedz

21

Z powodzeniem użyłem SMO do przywrócenia bazy danych. Podzielę się moim kodem. Mam nadzieję, że to pomoże. To rozwiązanie ma jedno zastrzeżenie, uważa, że ​​masz tylko jeden podstawowy plik danych. Dopasowanie logów i plików danych jest bardzo trudne i na wiele sposobów może się nie udać. W każdym razie spróbuj i daj mi znać, że to pomaga.

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.IO; 
using System.Text; 
using System.Threading; 
using Microsoft.SqlServer.Management.Common; 
using Microsoft.SqlServer.Management.Smo; 
using Microsoft.Win32; 

namespace DatabaseUtility 
{ 
    public class BackupRestore 
    { 
     static Server srv; 
     static ServerConnection conn; 

     public static void BackupDatabase(string serverName, string databaseName, string filePath) 
     { 
      conn = new ServerConnection(); 
      conn.ServerInstance = serverName; 
      srv = new Server(conn); 

      try 
      { 
       Backup bkp = new Backup(); 

       bkp.Action = BackupActionType.Database; 
       bkp.Database = databaseName; 

       bkp.Devices.AddDevice(filePath, DeviceType.File); 
       bkp.Incremental = false; 

       bkp.SqlBackup(srv); 

       conn.Disconnect(); 
       conn = null; 
       srv = null; 
      } 

      catch (SmoException ex) 
      { 
       throw new SmoException(ex.Message, ex.InnerException); 
      } 
      catch (IOException ex) 
      { 
       throw new IOException(ex.Message, ex.InnerException); 
      } 
     } 

     public static void RestoreDatabase(string serverName, string databaseName, string filePath) 
     { 

      conn = new ServerConnection(); 
      conn.ServerInstance = serverName; 
      srv = new Server(conn); 

      try 
      { 
       Restore res = new Restore(); 

       res.Devices.AddDevice(filePath, DeviceType.File); 

       RelocateFile DataFile = new RelocateFile(); 
       string MDF = res.ReadFileList(srv).Rows[0][1].ToString(); 
       DataFile.LogicalFileName = res.ReadFileList(srv).Rows[0][0].ToString(); 
       DataFile.PhysicalFileName = srv.Databases[databaseName].FileGroups[0].Files[0].FileName; 

       RelocateFile LogFile = new RelocateFile(); 
       string LDF = res.ReadFileList(srv).Rows[1][1].ToString(); 
       LogFile.LogicalFileName = res.ReadFileList(srv).Rows[1][0].ToString(); 
       LogFile.PhysicalFileName = srv.Databases[databaseName].LogFiles[0].FileName; 

       res.RelocateFiles.Add(DataFile); 
       res.RelocateFiles.Add(LogFile); 

       res.Database = databaseName; 
       res.NoRecovery = false; 
       res.ReplaceDatabase = true; 
       res.SqlRestore(srv); 
       conn.Disconnect(); 
      } 
      catch (SmoException ex) 
      { 
       throw new SmoException(ex.Message, ex.InnerException); 
      } 
      catch (IOException ex) 
      { 
       throw new IOException(ex.Message, ex.InnerException); 
      } 
     } 

     public static Server Getdatabases(string serverName) 
     { 
      conn = new ServerConnection(); 
      conn.ServerInstance = serverName; 

      srv = new Server(conn); 
      conn.Disconnect(); 
      return srv; 

     } 
    } 
} 
+0

Ten kod naprawdę mi pomógł, z kilkoma modyfikacjami. Potrzebowałem przywrócić DB do innej lokalizacji i że rzeczy "RelocateFiles", złożone, jak to jest, działały dobrze. – Jez

+0

Witam, jaki jest cel przenoszenia plików w operacji przywracania bazy danych? –

+0

@RustyWizard Czasami pliki bazy danych nie są obecne w domyślnej lokalizacji. W takim przypadku musimy znaleźć plik i użyć go w poleceniu przywracania, aby podczas przywracania nie wystąpiły żadne błędy. –