Neste artigo vou mostrar como realizar o backup e a restauração de um banco de dados SQL Server usando os recursos do SQL Server Management Objects (SMO).
O backup e a restauração de um banco de dados é uma tarefa crítica, pois visa manter a integridade e a segurança das informações armazenadas.
Para grandes aplicações, a realização do backup e restauração em geral fica sob responsabilidade de um DBA, mas para aplicações menores, a responsabilidade fica por conta do desenvolvedor e isso pode ser uma tarefa espinhosa, visto que temos diversas versões do SQL Server, diversos tipos de backups, etc.
Neste artigo eu vou mostrar como podemos realizar a restauração e o backup do banco de dados SQL Server em uma aplicação Windows Forms usando a linguagem C# para a versão do SQL Server 2012 e utilizando os recursos do SQL Server Management Objects (SMO) que é uma coleção de namespaces que, por sua vez, contêm diferentes classes, interfaces, delegados e enumerações, para trabalhar e gerenciar uma instância do SQL Server via programação.
O SMO estende e substitui os Objetos de Gerenciamento Distribuído do SQL Server (SQL-DMO) que foi usado para versões mais antigas do SQL Server (SQL Server 2000). Portanto, veremos como usar o SMO e como gerenciar programaticamente uma instância do SQL Server usando C#.
Nota: Os aplicativos que usam SMO e que foram escritos usando versões anteriores do SQL Server podem ser recompilados usando SMO no SQL Server atual. As referências à dlls do SMO em versões antigas do SQL Server devem ser removidas e as referências às novas dll do SMO fornecidas com o SQL Server atual devem ser incluídas.
Apresentando o SMO
O modelo de objeto SMO representa o SQL Server como uma hierarquia de objetos. No topo dessa hierarquia, está o objeto Server. Abaixo dele residem todas as demais classes de instância.
As classes SMO podem ser agrupadas em duas categorias:
– Classes de instância: Os objetos do SQL Server são representados por classes de instância. Elas formam uma hierarquia que se assemelha à hierarquia de objetos do servidor de banco de dados. No topo desta hierarquia está o objeto Server e, por isso, existe uma hierarquia de objetos de instância que incluem: bancos de dados, tabelas, colunas, triggers, índices, funções definidas pelo usuário, procedimentos armazenados, etc.
– Classes de utilidade: As classes de utilidade são independentes da instância do SQL Server e executam tarefas específicas. Essas classes foram agrupadas com base em suas funcionalidades. Por exemplo, operações de script de banco de dados, bancos de dados de backup e restauração, transferência de esquema, dados para outro banco de dados, etc.
No geral, para poder usar esses recursos você deverá usar as seguintes referências:
- Microsoft.SqlServer.ConnectionInfo
- Microsoft.SqlServer.Smo
- Microsoft.SqlServer.Management.Sdk.Sfc
- Microsoft.SqlServer.SmoExtended
Além dessas classes, temos também as classes dos seguintes namespaces:
Microsoft.SqlServer.Management.Common | Contém as classes que você precisará para estabelecer uma conexão com uma instância do SQL Server e executar instruções Transact-SQL diretamente. |
Microsoft.SqlServer.Management.Smo | Este é o namespace básico que você precisará em todos os aplicativos SMO, ele fornece classes para funcionalidades SMO essenciais. Ele contém classes de utilidade, classes de instâncias, enumerações, tipos de manipuladores de eventos e diferentes tipos de exceções. |
Microsoft.SqlServer.Management.Smo.Agent | Fornece as classes para gerenciar o SQL Server Agent, por exemplo, para gerenciar Job, Alerts, etc. |
Microsoft.SqlServer.Management.Smo.Broker | Fornece classes para gerenciar componentes do Service Broker usando SMO. |
Microsoft.SqlServer.Management.Smo.Wmi | Fornece classes que representam o SQL Server Windows Management Instrumentation (WMI). Com essas classes, você pode iniciar, parar e pausar os serviços do SQL Server, alterar os protocolos e as bibliotecas de rede, etc |
Instalando o SMO
Para podermos usar os recursos do SMO, temos que instala-lo. Você deve selecionar o SDK de Ferramentas do Cliente quando instalar o SQL Server. Para instalar o Client Tooks SDK sem instalar o SQL Server, instale o Shared Management Objects do pacote de recursos do SQL Server.
Se você quiser garantir que o SQL Server Management Objects esteja instalado em um computador que executará seu aplicativo, você pode usar os Shared Management Objects (Objetos de gerenciamento compartilhado) .msi no pacote de recursos do SQL Server.
Por padrão, os assemblies SMO estão instalados no diretório C:\Program Files\Microsoft SQL Server\130\SDK\Assemblies\.
A seguir, inclua as referências ao SMO via menu Project, opção Add Reference:
A partir da ToolBox, inclua os seguintes controles no formulário:
- 1 Panel
- 1 PictureBox
- 4 Label
- 2 TextBox – txtUsuario, txtSenha
- 2 Combobox – cboServidor , cboDatabase
- 5 Buttons – btnAlterarServidor, btnAlterarDatabase, btnBackup, btnRestore e btnEncerrar
- 1 checkbox – chkIntegratedSecurity
Disponha os controles conforme o layout da figura abaixo:
Defina os seguintes namespaces no formulário:
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using System;
using System.Data;
using System.IO;
using System.Windows.Forms;
Declare as seguintes variáveis no formulário:
//enumera uma lista de instâncias locais disponíveis do SQL Server
DataTable tabelaServidores = SmoApplication.EnumAvailableSqlServers(true);
//define o objeto do tipo Server
private static Server servidor;
//define o caminho para o backup/restore (pasta bin/Debug)
private string DBpath = Application.StartupPath;
1- No evento Load do formulário, digite o código abaixo:
private void Form1_Load(object sender, EventArgs e) { this.Cursor = Cursors.Default; WindowState = FormWindowState.Normal; cboServidor.Enabled = false; cboDataBase.Enabled = false; try { chkIntegratedSecurity.Checked = true; // Se existerem servidores if (tabelaServidores.Rows.Count > 0) { // Percorre cada servidor na tabela foreach (DataRow drServer in tabelaServidores.Rows) { cboServidor.Items.Add(drServer["Name"]); cboServidor.Text = Convert.ToString(drServer["Name"]); } } } catch (Exception) { // Inicie o serviço do SQL Server Browser se não conseguir carregar os servidores.(http://msdn.microsoft.com/en-us/library/ms165734(v=sql.90).aspx MessageBox.Show("ERROR: Não existem servidores disponíveis.\nOu ocorreu um erro ao carregar os servidores", "Servidor Erro", MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { this.Cursor = Cursors.Default; } this.Cursor = Cursors.Default; }
O código já esta comentado, mas vale ressaltar que a operação de carregar o combobox com as instâncias locais do SQL Server pode demorar. Se por algum motivo não carregar nenhuma instância, então tente habilitar o serviço do SQL Server Browser.
A seguir, o código do evento SelectedValueChanged dos combobox que desabilita os combox e o código do evento Click dos botões Alterar (servidor e database) habilita os combobox:
private void cboServidor_SelectedValueChanged(object sender, EventArgs e) { //habilita o combobox dos servidores cboServidor.Enabled = false; } private void cboDataBase_SelectedValueChanged(object sender, EventArgs e) { //habilita o combobox dos databases cboDataBase.Enabled = false; } private void btnAlterarDatabase_Click(object sender, EventArgs e) { //habilita o combobox dos databases cboDataBase.Enabled = true; } private void btnAlterarServidor_Click(object sender, EventArgs e) { //habilita o combobox dos servidores cboServidor.Enabled = true; }
Código do evento CheckedChanged do controle CheckBox que verifica se esta marcado ou não e altera as propriedades dos TextBox para o usuário e senha:
private void chkIntegratedSecurity_CheckedChanged(object sender, EventArgs e) { //verifica se o checkbox esta marcado ou desmarcado e altera as propriedades dos TextBox if (chkIntegratedSecurity.CheckState == CheckState.Checked) { txtUsuario.Enabled = false; txtUsuario.Text = string.Empty; txtSenha.Enabled = false; txtSenha.Text = string.Empty; } if (chkIntegratedSecurity.CheckState == CheckState.Unchecked) { txtUsuario.Enabled = true; txtSenha.Enabled = true; } }
Código do evento Click do combobox – cboDataBase – que carrega o controle com o nome dos bancos de dados selecionados para a instância do servidor selecionada:
private void cboDataBase_Click(object sender, EventArgs e) { //limpa o combobox dos databases cboDataBase.Items.Clear(); try { //se foi selecionado um servidor if (cboServidor.SelectedItem != null && cboServidor.SelectedItem.ToString() != "") { this.Cursor = Cursors.WaitCursor; // Cria uma nova conexão com o servidor selecionado ServerConnection srvConn = new ServerConnection(cboServidor.SelectedItem.ToString()); // Faz o Login usando a autenticacao SQL ao invés da autenticação do Windows srvConn.LoginSecure = true; //tipo de conexão não exige usuário e senha(usa a autenticação do windows) if (chkIntegratedSecurity.CheckState == CheckState.Checked) { // Cria um novo objeto SQL Server usando a conexão criada servidor = new Server(srvConn); // percorre a lista de banco de dados foreach (Database dbServer in servidor.Databases) { // Adiciona o banco de dados na combobox cboDataBase.Items.Add(dbServer.Name); } } //tipo de conexão exige usuário e senha if (chkIntegratedSecurity.CheckState == CheckState.Unchecked) { // atribui o nome do usuário srvConn.Login = txtUsuario.Text; // atribui a senha srvConn.Password = txtSenha.Text; // Cria um novo objeto SQL Server usando a conexão criada servidor = new Server(srvConn); // percorre a lista de banco de dados foreach (Database dbServer in servidor.Databases) { // Adiciona o banco de dados na combobox cboDataBase.Items.Add(dbServer.Name); } } } else { // Um servidor não foi selecionado exibe um erro MessageBox.Show("ERROR: Contate o Administrador!!", "Servidor", MessageBoxButtons.OK, MessageBoxIcon.Error); } } catch (Exception) { // Inicie o serviço do SQL Server Browser se não conseguir carregar os servidores.(http://msdn.microsoft.com/en-us/library/ms165734(v=sql.90).aspx MessageBox.Show("ERROR: Ocorreu um erro durante a carga dos banco de dados disponíveis", "Server", MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { this.Cursor = Cursors.Arrow; } }
Executando o projeto iremos obter o seguinte resultado:
Agora defina o seguinte código no evento Click do botão de comando Backup:
private void btnBackup_Click(object sender, EventArgs e) { //verifica se um banco de dados foi selecionado if (cboDataBase.SelectedIndex.ToString().Equals("")) { MessageBox.Show("Selecione um Database", "Server", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } //se o objeto servidor for diferente de null temos uma conexão if (servidor != null) { try { //desabilita os botões btnBackup.Enabled = false; btnRestore.Enabled = false; btnAlterarDatabase.Enabled = false; btnAlterarServidor.Enabled = false; //Este codigo é usado se você já criou o arquivo de backup. File.Delete(DBpath + "\\backup.bak"); this.Cursor = Cursors.WaitCursor; // se o usuário escolheu um caminho onde salvar o backup // Cria uma nova operação de backup Backup bkpDatabase = new Backup(); // Define o tipo de backup type para o database bkpDatabase.Action = BackupActionType.Database; // Define o database que desejamos fazer o backup bkpDatabase.Database = cboDataBase.SelectedItem.ToString(); // Define o dispositivo do backup para : file BackupDeviceItem bkpDevice = new BackupDeviceItem(DBpath + "\\Backup.bak", DeviceType.File); // Adiciona o dispositivo de backup ao backup bkpDatabase.Devices.Add(bkpDevice); // Realiza o backup bkpDatabase.SqlBackup(servidor); MessageBox.Show("Backup do Database " + cboDataBase.Text + " criado com sucesso", "Servidor", MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception x) { MessageBox.Show("ERRO: Ocorreu um erro durante o BACKUP do DataBase" + x, "Erro no Servidor", MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { this.Cursor = Cursors.Arrow; //habilita os botões btnBackup.Enabled = true; btnRestore.Enabled = true; btnAlterarDatabase.Enabled = true; btnAlterarServidor.Enabled = true; } } else { MessageBox.Show("ERRO: Não foi estabelecida uma conexão com o SQL Server", "Servidor", MessageBoxButtons.OK, MessageBoxIcon.Error); this.Cursor = Cursors.Arrow; } }
Lembrando que o backup foi definido para o tipo de dispositivo FILE e que o arquivo .bak será copiado na pasta \bin\debug do projeto.
Código do evento Click do botão Restore:
private void btnRestore_Click(object sender, EventArgs e) { //verifica se foi selecoinado um banco de dados if (cboDataBase.SelectedIndex.ToString().Equals("")) { MessageBox.Show("Escolha um banco de dados", "Servidor", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } // Se existir um conexão SQL Server criada if (servidor != null) { try { //desabilita os botões btnBackup.Enabled = false; btnRestore.Enabled = false; btnAlterarDatabase.Enabled = false; btnAlterarServidor.Enabled = false; this.Cursor = Cursors.WaitCursor; // Se foi escolhido o arquivo o arquivo que deseja ser restaurado // Cria uma nova operação de restore Restore rstDatabase = new Restore(); // Define o tipo de restore para o banco de dados rstDatabase.Action = RestoreActionType.Database; // Define o database que desejamos restaurar rstDatabase.Database = cboDataBase.SelectedItem.ToString(); // Define o dispostivo de backup a partir do qual vamos restaurar o arquivo BackupDeviceItem bkpDevice = new BackupDeviceItem(DBpath + "\\Backup.bak", DeviceType.File); // Adiciona o dispositivo de backup ao tipo de restore rstDatabase.Devices.Add(bkpDevice); // Se o banco de dados ja existe então subsititui rstDatabase.ReplaceDatabase = true; // Realiza o Restore rstDatabase.SqlRestore(servidor); MessageBox.Show("Database " + cboDataBase.Text + " RESTAURADO com sucesso", "Servidor", MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception) { MessageBox.Show("ERRO: Ocorreu um erro durante a restauração do banco de dados", "Erro na aplicação", MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { this.Cursor = Cursors.Arrow; //habilita os botões btnBackup.Enabled = true; btnRestore.Enabled = true; btnAlterarDatabase.Enabled = true; btnAlterarServidor.Enabled = true; } } else { MessageBox.Show("ERRO: Não foi estabelecida uma conexão com o SQL Server", "Servidor", MessageBoxButtons.OK, MessageBoxIcon.Error); this.Cursor = Cursors.Arrow; } }
Executando o projeto, teremos o seguinte resultado:
O projeto foi testado com o SQL Server 2012. Para versões anteriores pode ser necessário ajustes no código.
Pegue o código do projeto aqui: CShp_SQLServerBackupRestore.zip
Até o próximo artigo!