none
Backup y Restore a sql de visual basic 2010

    Pregunta

  • Buenas a todos. 

    Programo en vb.net 2010 y uso SQL 2008

    En esta ocasión necesito un tutorial o material para realizar una copia de seguridad de mi base de datos desde visual Basic.

    Quiero resaltar que desde sql, yo sé hacer copia de seguridad, pero para más comodidad me gustaría hacerlo desde visual Basic.

    Esta opción de copia de seguridad que va a tener el sistema de ventas en vb.net, no es para el usuario final, sino para el programador.

    Luego de yo pode hacer mi copia de seguridad, si se puede, como restaurar la copia de seguridad también desde visual BASIC.

    dentro de vb.net tengo el diseñó en un formulario, con dos botones: 

    1) Boton Copia de Seguridad

    2) Restaurar Copia de Seguridad. 

    Imports System.Data.SqlClient
    Public Class Form1
        Dim cn As New SqlConnection("Data Source = (local); Initial Catalog = DbSistemaFactura; User Id=xxx; Password=123;")
        Dim da As SqlDataAdapter
        Dim dst As DataSet
        Private Sub BTN_CARPETA_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BTN_CARPETA.Click
            Me.FolderBrowserDialog1.ShowDialog()
            Me.TXT_CARPETA.Text = Me.FolderBrowserDialog1.SelectedPath
        End Sub
    
        Private Sub BTN_CREAR_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BTN_CREAR.Click
            Dim nombre As String
            'Dim nombre2 As String
    
    
            nombre = Me.TXT_NOMBRE.Text & ".bak"
            da = New SqlDataAdapter("BACKUP DATABASE DbSistemaFactura TO DISK ='" & Me.TXT_CARPETA.Text & nombre & "' WITH INIT , NOUNLOAD , NAME ='" & Me.TXT_NOMBRE.Text & "', NOSKIP , STATS = 10, NOFORMAT", cn)
            dst = New DataSet
            da.Fill(dst)
            MessageBox.Show("SE CREO EL BACKUP CORRECTAMENTE")
        End Sub
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    
        End Sub
    End Class

    E iniciado con este código, y funciona pero solo el Backup

    Cuento con ustedes. 




    • Editado EliannyRD lunes, 9 de enero de 2017 22:20
    domingo, 8 de enero de 2017 15:33

Respuestas

  • La idea que tienes es en principio correcta, es decir, desde VB lo que hay que hacer es enviar un comando SQL del tipo "BACKUP DATABASE...". Pero para eso no es adecuado usar un SqlDataAdapter; lo correcto es usar el método ExecuteNonQuery de un SqlCommand.

    Ten presente que cuando pones TO DISK='c:\loquesea', esa ubicación está en el disco del servidor SQL, no en el PC desde el que ejecutas el programa en VB.

    Para el restore se hace lo mismo, es decir, transmitir un comando "RESTORE DATABASE..." con todas las opciones que se supone que ya conoces puesto que lo sabes hacer desde el SQL. El único truco que hay que tener en cuenta, es que no se puede restaurar una base de datos mientras está abierta y en uso. Y si el programa la estaba usando antes de que usaras el botón de restaurar, entonces está ocupada y no puede restaurarse (ni siquiera aunque hagas un close de la conexión, porque el Pool la mantiene abierta). E incluso aunque no la abrieses, podrían haberla abierto desde otro puesto. La solución es abrir una conexión a la master (y no a la BD que quieres restaurar) y desde esa conexión enviar este comando:

    alter database [comoSeLlame] set single_user with rollback immediate

    Eso cierra todas las conexiones, y a continuación ya puedes enviar el restore database. Por supuesto les aparecerá un error (que puedes interceptar con try...catch) a los procesos que tuvieran abiertas esas conexiones cuyo cierre acabas de forzar.

    • Propuesto como respuesta Willams Morales domingo, 8 de enero de 2017 21:23
    • Marcado como respuesta EliannyRD lunes, 9 de enero de 2017 16:02
    • Desmarcado como respuesta EliannyRD lunes, 9 de enero de 2017 16:03
    • Marcado como respuesta EliannyRD martes, 10 de enero de 2017 21:12
    domingo, 8 de enero de 2017 20:31
  • puedes poner el ejemplo de la forma correcta de como crear el Backup

    Para hacer el Backup con ExecuteNonQuery en lugar de un dataadapter:

    Dim cn As New SqlConnection("Data Source = (local); Initial Catalog = DbSistemaFactura; User Id=saAdmin; Password=CECOMCE;")
    Dim sql as String = "BACKUP DATABASE DbSistemaFactura TO DISK ='" & Me.TXT_CARPETA.Text & nombre & "' WITH INIT , NOUNLOAD , NAME ='" & Me.TXT_NOMBRE.Text & "', NOSKIP , STATS = 10, NOFORMAT"
    Dim cmd as New SqlCommand(sql, cn)
    cmd.ExecuteNonQuery()

    El restore es similar pero poniendo la sentencia de restore, y cambiando el SqlConnection para que conecte a "master".

    Ojo con los textboxes que concatenas en la sentencia, cerciórate de que primero validas lo que el usuario ha escrito en esos textboxes para que no te introduzcan inyecciones de SQL.

    • Marcado como respuesta EliannyRD lunes, 9 de enero de 2017 16:02
    • Desmarcado como respuesta EliannyRD lunes, 9 de enero de 2017 16:03
    • Marcado como respuesta EliannyRD martes, 10 de enero de 2017 21:13
    domingo, 8 de enero de 2017 22:49

Todas las respuestas

  • La idea que tienes es en principio correcta, es decir, desde VB lo que hay que hacer es enviar un comando SQL del tipo "BACKUP DATABASE...". Pero para eso no es adecuado usar un SqlDataAdapter; lo correcto es usar el método ExecuteNonQuery de un SqlCommand.

    Ten presente que cuando pones TO DISK='c:\loquesea', esa ubicación está en el disco del servidor SQL, no en el PC desde el que ejecutas el programa en VB.

    Para el restore se hace lo mismo, es decir, transmitir un comando "RESTORE DATABASE..." con todas las opciones que se supone que ya conoces puesto que lo sabes hacer desde el SQL. El único truco que hay que tener en cuenta, es que no se puede restaurar una base de datos mientras está abierta y en uso. Y si el programa la estaba usando antes de que usaras el botón de restaurar, entonces está ocupada y no puede restaurarse (ni siquiera aunque hagas un close de la conexión, porque el Pool la mantiene abierta). E incluso aunque no la abrieses, podrían haberla abierto desde otro puesto. La solución es abrir una conexión a la master (y no a la BD que quieres restaurar) y desde esa conexión enviar este comando:

    alter database [comoSeLlame] set single_user with rollback immediate

    Eso cierra todas las conexiones, y a continuación ya puedes enviar el restore database. Por supuesto les aparecerá un error (que puedes interceptar con try...catch) a los procesos que tuvieran abiertas esas conexiones cuyo cierre acabas de forzar.

    • Propuesto como respuesta Willams Morales domingo, 8 de enero de 2017 21:23
    • Marcado como respuesta EliannyRD lunes, 9 de enero de 2017 16:02
    • Desmarcado como respuesta EliannyRD lunes, 9 de enero de 2017 16:03
    • Marcado como respuesta EliannyRD martes, 10 de enero de 2017 21:12
    domingo, 8 de enero de 2017 20:31
  • Gracias por responder Willams Morales

    puedes poner el ejemplo de la forma correcta de como crear el Backup y Restore.

    o por lo menos hacer el Backup de la forma correcta. 

    Gracias...



    • Editado EliannyRD domingo, 8 de enero de 2017 22:33
    domingo, 8 de enero de 2017 22:30
  • puedes poner el ejemplo de la forma correcta de como crear el Backup

    Para hacer el Backup con ExecuteNonQuery en lugar de un dataadapter:

    Dim cn As New SqlConnection("Data Source = (local); Initial Catalog = DbSistemaFactura; User Id=saAdmin; Password=CECOMCE;")
    Dim sql as String = "BACKUP DATABASE DbSistemaFactura TO DISK ='" & Me.TXT_CARPETA.Text & nombre & "' WITH INIT , NOUNLOAD , NAME ='" & Me.TXT_NOMBRE.Text & "', NOSKIP , STATS = 10, NOFORMAT"
    Dim cmd as New SqlCommand(sql, cn)
    cmd.ExecuteNonQuery()

    El restore es similar pero poniendo la sentencia de restore, y cambiando el SqlConnection para que conecte a "master".

    Ojo con los textboxes que concatenas en la sentencia, cerciórate de que primero validas lo que el usuario ha escrito en esos textboxes para que no te introduzcan inyecciones de SQL.

    • Marcado como respuesta EliannyRD lunes, 9 de enero de 2017 16:02
    • Desmarcado como respuesta EliannyRD lunes, 9 de enero de 2017 16:03
    • Marcado como respuesta EliannyRD martes, 10 de enero de 2017 21:13
    domingo, 8 de enero de 2017 22:49
  • Gracias a todos

    Resuelto 90x%

    El código me quedó así: 

    Private Sub BTN_CARPETA_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BTN_CARPETA.Click
            Me.FolderBrowserDialog1.ShowDialog()
            Me.TXT_CARPETA.Text = Me.FolderBrowserDialog1.SelectedPath
        End Sub


    Private Sub BTN_CREAR_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BTN_CREAR.Click
            Dim nombre As String
            nombre = Me.TXT_NOMBRE.Text & ".bak"
    
    
            Using cnx As New SqlConnection("Data Source = (local); Initial Catalog = DbSistemaFactura; User Id=saAdmin; Password=CECOMCE;")
    
                cnx.Open()
    
                Dim actualizar As String = "BACKUP DATABASE DbSistemaFactura TO DISK ='" & Me.TXT_CARPETA.Text & nombre & "' WITH INIT , NOUNLOAD , NAME ='" & Me.TXT_NOMBRE.Text & "', NOSKIP , STATS = 10, NOFORMAT"
    
                Using cmd As New SqlCommand(actualizar, cnx)
    
                    cmd.ExecuteNonQuery()
                    MsgBox("SE CREO EL BACKUP CORRECTAMENTE ")
    
                End Using
            End Using
    
        End Sub

    tiene un pequeño problema, cuando eligo una caprtea que está en c:, el Backup no se guarda dentro de la carpeta, sino fuera en la unidad C: 

    solo me falta el Restore. 




    • Editado EliannyRD lunes, 9 de enero de 2017 16:07
    lunes, 9 de enero de 2017 16:01
  • y que paso, con el Restore, se puede hacer

    si se puede hacer peguen el codigo. 

    Gracias..........................

    lunes, 9 de enero de 2017 19:07
  • Buenas, el Bakup, me funciona bien, me pueden por favor ayudar con el Restore.

    Favor de poner el código. 

    lunes, 11 de diciembre de 2017 22:37
  • Mejor hazlo al reves: Ponnos el codigo que has escrito para el Restore, y asi lo analizamos y tratamos de explicar donde esta el error.

    Recuerda tambien aportar cual es el mensaje de error exacto que sale; eso ayuda mucho a detectar cual es el problema concreto.

    Si lo que sucede no es que te de un error, sino que ni siquiera lo has escrito todavia, entonces ponnos el codigo que escribiste para el backup y explica cual es la dificultad que encuentras para sustituir dentro de ese codig la sentencia backup por una sentencia restore tal como se indica en la primera respuesta.

    martes, 12 de diciembre de 2017 12:03
  • Gracias. 

    Programo en vb.net y uso SQL Server

    Imports System.Data.SqlClient
    Public Class Form1
        Dim con, con1 As SqlConnection
        Dim cmd As SqlCommand
        Dim dread As SqlDataReader
       
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            'En esta parte solamente se coloca el nombre del servidor. 
    
            'server("(local)")
            'server("DESKTOP-LJRIODK") es el nombre del equipo. 
            server(".") 'es lo mismo que lo de arriba.
    
    
            'server(".\sqlexpress")
        End Sub
        Sub server(ByVal str As String)
            con = New SqlConnection("Data Source=" & str & ";Database=Master;integrated security=SSPI;")
            con.Open()
            cmd = New SqlCommand("select *  from sysservers  where srvproduct='SQL Server'", con)
            dread = cmd.ExecuteReader
            While dread.Read
                cmbserver.Items.Add(dread(2))
            End While
            dread.Close()
        End Sub
        Sub connection()
            con = New SqlConnection("Data Source=" & Trim(cmbserver.Text) & ";Database=Master;integrated security=SSPI;")
            con.Open()
            cmbdatabase.Items.Clear()
            cmd = New SqlCommand("select * from sysdatabases", con)
            dread = cmd.ExecuteReader
            While dread.Read
                cmbdatabase.Items.Add(dread(0))
            End While
            dread.Close()
        End Sub
    
        Private Sub cmbserver_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmbserver.SelectedIndexChanged
            connection()
        End Sub
        Sub query(ByVal que As String)
            On Error Resume Next
            cmd = New SqlCommand(que, con)
            cmd.ExecuteNonQuery()
        End Sub
        Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
            If ProgressBar1.Value = 100 Then
                Timer1.Enabled = False
                ProgressBar1.Visible = False
                MsgBox("Hecho exitosamente")
            Else
                ProgressBar1.Value = ProgressBar1.Value + 5
            End If
        End Sub
        Sub blank(ByVal str As String)
            If cmbserver.Text = "" Or cmbdatabase.Text = "" Then
                MsgBox("Server Name & Database Blank Field")
                Exit Sub
            Else
                If str = "backup" Then
                    SaveFileDialog1.FileName = cmbdatabase.Text
                    SaveFileDialog1.ShowDialog()
                    Timer1.Enabled = True
                    ProgressBar1.Visible = True
                    Dim s As String
                    s = SaveFileDialog1.FileName
                    query("backup database " & cmbdatabase.Text & " to disk='" & s & "'")
                ElseIf str = "restore" Then
                    OpenFileDialog1.ShowDialog()
                    Timer1.Enabled = True
                    ProgressBar1.Visible = True
                    query("RESTORE DATABASE " & cmbdatabase.Text & " FROM disk='" & OpenFileDialog1.FileName & "'")
                End If
            End If
        End Sub
        Private Sub cmbbackup_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmbbackup.Click
            blank("backup")
        End Sub
    
        Private Sub cmdrestore_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdrestore.Click
            blank("restore")
        End Sub
    End Class
    

    Quiero resaltar que Backup funciona nítido, pero el Restore no hace nada, ni da mensaje de error 

    Saludos cordiales 

    martes, 12 de diciembre de 2017 19:47
  • Tiene pinta de estar bien. El comando "restore database..." es correcto, y el método "query" abre una conexión contra "master", que también es correcto (lo malo sería que la abriera contra la propia base de datos que se quiere restaurar, cosa que fallaría).

    Se me ocurren un par de cosas que pueden fallar, pero que no se pueden comprobar examinando ese fragmento de código fuente:

    - Si previamente el programa ha abierto en algún momento una conexión a la base de datos que se quiere restaurar, esa conexión queda abierta en el Pool de conexiones, e impide restaurar la base de datos.

    - Puesto que la sentencia "restore..." no incluye un "move...", los ficheros de datos se intentan restaurar sobre la misma ubicación del disco en la que estaban cuando se tomó el backup. Si esa ubicación no está disponible en la máquina donde se restaura, da lugar a un error.

    Pero en ambos casos se produciría una excepción, no ocurriría el "no hace nada". ¿No tendrás activado en la aplicación algún manejador de excepciones que "se las esté tragando"?

    martes, 12 de diciembre de 2017 21:48
  • ahí te envío el proyecto de Backup Restore, para que lo pruebes. 



    https://drive.google.com/drive/folders/13PF1DT148NLHC9LRURoNFoajzK_DjObN?usp=sharing
    • Editado EliannyRD martes, 12 de diciembre de 2017 22:31
    martes, 12 de diciembre de 2017 22:25
  • Le he echado un vistazo, y no veo ningún defecto que resulte obvio en el código. Más bien me inclino por alguna de las dos cosas que te mencionaba: que se haya abierto antes alguna conexión a la base de datos que se intenta restaurar, o que la ubicación en disco de los ficheros esté ocupada. ¿Has probado a seguirlo paso a paso con el debugger y ver qué sucede exactamente en el momento de pasar por la sentencia Restore? O a capturar la sentencia SQL con el Profiler desde el lado servidor, a ver qué le llega, y copiarla y pegarla en SSMS y ver qué error da al ejecutarla.
    lunes, 18 de diciembre de 2017 19:27