none
Editar (UPDATE) multiples filas en Datagridview?

    Pregunta

  • Buen día a todos,

    verán, tengo este problema. Tengo un DGV en donde inserto multiples filas a la vez con INSERT INTO, cuando hago un select de esos datos para poder modificarlos/editar, me actualiza todo el DGV con los datos de la última fila,<o:p></o:p>

    Por ejemplo si inserto estos datos todo funciona bien, pero cuando quiero hacer update no me deja agregar ni quitar filas, y si edito cualquier valor, todo se reemplaza con la última fila,<o:p></o:p>

    Por ejemplo tengo estos datos previamente guardados

    Al cargar esos datos y si quiero modificar cualquier valor

    Al hacer clic en el botón editar, todos los datos se reemplazan con los valores de la última fila, en este caso Sara

    Uso este código:

        For Each row As DataGridViewRow In ReferenciasDataGridView.Rows
            Using con As New SqlConnection(conexRef)
    
                If con.State = ConnectionState.Closed Then
                    con.Open()
    
                End If
    
                Using cmd As New SqlCommand("UPDATE referencias " _
                                            & "SET nombre = @nombre, F = @F" _
                                            & "valor1 = @valor1, valor2 = @valor2, " _
                                            & "WHERE (clave_exam = @clave_exam)", con)
    
                    cmd.Parameters.Clear()
                    cmd.Parameters.AddWithValue("@nombre", row.Cells(1).Value)
                    cmd.Parameters.AddWithValue("@F", row.Cells(2).Value)
                    cmd.Parameters.AddWithValue("@valor1", row.Cells(3).Value)
                    cmd.Parameters.AddWithValue("@valor2", row.Cells(4).Value)

    Cómo se puede resolver esto?

    Gracias y saludos!

    jueves, 13 de octubre de 2016 23:57

Respuestas

  • Hola Datos de datagridview a otro formulario,

    Puedes intentar haciendo estos cambios, no es necesario crear una conexión en cada iteración del ForEach y menos crear un SQLCommand para cada uno, ya que usan la misma consulta.

    Private Sub btnEditar_Click(sender As Object, e As EventArgs) Handles btnEditar.Click
            Try
                Using con As New SqlConnection("MiCadenaConexion")
                    con.Open()
    
                    Dim query = "UPDATE referencias " &
                                "SET nombre = @nombre, F = @F " &
                                "valor1 = @valor1, valor2 = @valor2, " &
                                "WHERE (clave_exam = @clave_exam)"
    
                    Dim cmd As New SqlCommand(query, con)
    
                    'Recorre los campos...
                    For Each Row As DataGridViewRow In ReferenciasDataGridView.Rows
    
                        cmd.Parameters.Clear()
                        cmd.Parameters.AddWithValue("@nombre", CStr(Row.Cells(1).Value))
                        cmd.Parameters.AddWithValue("@F", CStr(Row.Cells(2).Value))
                        cmd.Parameters.AddWithValue("@valor1", CStr(Row.Cells(3).Value))
                        cmd.Parameters.AddWithValue("@valor2", CStr(Row.Cells(4).Value))
                        cmd.Parameters.AddWithValue("@clave_exam", PonerLaCelda)
    
                        'Ejecuta la consulta
                        cmd.ExecuteNonQuery()
                    Next
    
                    MessageBox.Show("Correcto")
    
                End Using
            Catch ex As Exception
                MessageBox.Show(ex.Message)
            End Try
        End Sub

    En este caso uso la función CStr(...) para convertir los valores de la fila a string, en caso sean de otro tipo cambiar el tipo de conversión, ya que el .Value de cada fila devuelve un valor de tipo Object lo que generaría error si activas el Option Strict On.

    Saludos.


    JC NaupaCrispín
    Lima - Perú

    La magia no existe, la programación SI

    • Marcado como respuesta Juan Ortiz T viernes, 14 de octubre de 2016 0:55
    viernes, 14 de octubre de 2016 0:17
  • Hola Juan Ortiz T,

    Puedes echarle un ojo al siguiente link :

    Depuración con Visual Studio: Puntos de interrupción condicionales

    Básicamente es crear un punto de interrupción en la parte de :

    Private Sub btnEditar_Click() ... '<--- Aquí
    .....
    ....
    ....
    End Sub '<-- Aquí

    Para que cuando se ejecute ese código comience. Usarías la tecla F10 para pasar de línea :

    - Muestro un ejemplo de un For, obtengo el valor por cada iteración.

    Saludos.


    JC NaupaCrispín
    Lima - Perú

    La magia no existe, la programación SI

    • Marcado como respuesta Juan Ortiz T jueves, 20 de octubre de 2016 1:50
    martes, 18 de octubre de 2016 3:44

Todas las respuestas

  • Hola Datos de datagridview a otro formulario,

    Puedes intentar haciendo estos cambios, no es necesario crear una conexión en cada iteración del ForEach y menos crear un SQLCommand para cada uno, ya que usan la misma consulta.

    Private Sub btnEditar_Click(sender As Object, e As EventArgs) Handles btnEditar.Click
            Try
                Using con As New SqlConnection("MiCadenaConexion")
                    con.Open()
    
                    Dim query = "UPDATE referencias " &
                                "SET nombre = @nombre, F = @F " &
                                "valor1 = @valor1, valor2 = @valor2, " &
                                "WHERE (clave_exam = @clave_exam)"
    
                    Dim cmd As New SqlCommand(query, con)
    
                    'Recorre los campos...
                    For Each Row As DataGridViewRow In ReferenciasDataGridView.Rows
    
                        cmd.Parameters.Clear()
                        cmd.Parameters.AddWithValue("@nombre", CStr(Row.Cells(1).Value))
                        cmd.Parameters.AddWithValue("@F", CStr(Row.Cells(2).Value))
                        cmd.Parameters.AddWithValue("@valor1", CStr(Row.Cells(3).Value))
                        cmd.Parameters.AddWithValue("@valor2", CStr(Row.Cells(4).Value))
                        cmd.Parameters.AddWithValue("@clave_exam", PonerLaCelda)
    
                        'Ejecuta la consulta
                        cmd.ExecuteNonQuery()
                    Next
    
                    MessageBox.Show("Correcto")
    
                End Using
            Catch ex As Exception
                MessageBox.Show(ex.Message)
            End Try
        End Sub

    En este caso uso la función CStr(...) para convertir los valores de la fila a string, en caso sean de otro tipo cambiar el tipo de conversión, ya que el .Value de cada fila devuelve un valor de tipo Object lo que generaría error si activas el Option Strict On.

    Saludos.


    JC NaupaCrispín
    Lima - Perú

    La magia no existe, la programación SI

    • Marcado como respuesta Juan Ortiz T viernes, 14 de octubre de 2016 0:55
    viernes, 14 de octubre de 2016 0:17
  • Hola Joel C. Naupa Crispín,

    antes que nada, quiero agradecer por el tiempo que diste para aportar de tus conocimiento.

    Resulta que hice lo que me aportaste, pero igual sigo teniendo el mismo resultado, solo se me actualiza los datos con los valores de la última fila para cada celda de cada misma columna.

    Olvidé comentar que en el DGV permito Insertar desde una celda hasta un renglón vacio, dependiendo de lo que se necesite, uso esto antes del executenonquery...

    If Not Row.IsNewRow Then
                            cmd.Parameters(0).Value =
                                If(Row.Cells(0).Value Is Nothing, DBNull.Value, Row.Cells(1).Value.ToString())

    Y así por cada parametro. Tendrá algo que ver eso?? O pensé que tal ves podría ser en el for each. Hay alguna otra forma de hacer un loop que recorra cada fila del DGV?

    Disculpa si es pregunta muy obvia, soy novato en programación todavía

    Saludos,






    viernes, 14 de octubre de 2016 0:59
  • Hola Juan Ortiz T,

    La verdad si está raro, puedes mostrar tu código final que estás utilizando ? De dónde tomas la clave_exam , ya que en el código que muestras no hay esa parte. Haz probado agregar un punto de interrupción y hacer seguimiento al código para saber los valores que tomas ?

    Aquí muestro un ejemplo de como registrar y/o actualizar las filas de un DGV usando Transacciones.

    Guardar registros de un datagridview en sql

    Saludos.


    JC NaupaCrispín
    Lima - Perú

    La magia no existe, la programación SI

    viernes, 14 de octubre de 2016 1:17
  • Claro,

    Tengo una clave principal y una clave para datos que utilizo como un formato, esta última clave puede tener varias filas, por eso la puse como no principal.

    Te muestro me código completo:

            Try
                Using con As New SqlConnection(conexRef)
    
                    Dim query = "UPDATE referencias " _
                                                & "SET nombre = @nombre, F = @F, " _
                                                & "valor1 = @valor1, valor2 = @valor2, WHERE (clave = @clave)"
    
                    Dim cmd As New SqlCommand(query, con)
    
                    'Recorre los campos...
                    For Each Row As DataGridViewRow In ReferenciasDataGridView.Rows
    
                        cmd.Parameters.Clear()
                       
                        cmd.Parameters.AddWithValue("@nombre", Row.Cells(1))
                        cmd.Parameters.AddWithValue("@F", Row.Cells(2))
                        cmd.Parameters.AddWithValue("@valor1", Row.Cells(3))
                        cmd.Parameters.AddWithValue("@valor2", Row.Cells(4))
                        cmd.Parameters.AddWithValue("@clave", Row.Cells(5))
    
                        If Not Row.IsNewRow Then
                            cmd.Parameters(1).Value =
                                If(Row.Cells(1).Value Is Nothing, DBNull.Value, Row.Cells(1).Value.ToString())
                            cmd.Parameters(2).Value =
                                If(Row.Cells(2).Value Is Nothing, DBNull.Value, Row.Cells(2).Value.ToString())
                            cmd.Parameters(3).Value =
                                If(Row.Cells(3).Value Is Nothing, DBNull.Value, Row.Cells(3).Value.ToString())
                            cmd.Parameters(4).Value =
                                If(Row.Cells(4).Value Is Nothing, DBNull.Value, Row.Cells(4).Value.ToString())
    
    
                            'Ejecuta la consulta
                            con.Open()
                            cmd.ExecuteNonQuery()
                            con.Close()
                        End If
    
                    Next
    
                    MessageBox.Show("Correcto")
    
                End Using
            Catch ex As Exception
                MessageBox.Show(ex.Message)
            End Try

    Ese es el código del botón editar, la clave no la pongo por que la tengo como referencia y el usuario no la edite una vez grabada

    Lo que pasa que depende del usuario puede o no dejar celdas vacías, pero también puede que sean valores númericos (enteros o decimales) o también pueden ser cadenas.





    viernes, 14 de octubre de 2016 1:42
  • Hola Juan Ortiz T,

    Primero, quita la coma innecesaria antes del Where, me parece raro que no te haya mostrado error alguno.

    valor1 = @valor1, valor2 = @valor2, WHERE (clave = @clave)

    Segundo, sólo vas a actualizar las filas que no sean IsNewRow, cierto ? Por lo que puedes hacer un filtro en el ForEach.

     'Recorre las filas que no sean nuevas
    For Each Row As DataGridViewRow In ReferenciasDataGridView.Rows.OfType(Of DataGridViewRow).
                                                  Where(Function(x) Not x.IsNewRow)
    
      cmd.Parameters.Clear()
      cmd.Parameters.AddWithValue("@nombre", If(String.IsNullOrEmpty(CStr(Row.Cells(1).Value)), DBNull.Value, Row.Cells(1).Value))
      cmd.Parameters.AddWithValue("@F", If(String.IsNullOrEmpty(CStr(Row.Cells(2).Value)), DBNull.Value, Row.Cells(2).Value))
      cmd.Parameters.AddWithValue("@valor1", If(String.IsNullOrEmpty(CStr(Row.Cells(3).Value)), DBNull.Value, Row.Cells(3).Value))
      cmd.Parameters.AddWithValue("@valor2", If(String.IsNullOrEmpty(CStr(Row.Cells(4).Value)), DBNull.Value, Row.Cells(4).Value))
      cmd.Parameters.AddWithValue("@clave_exam", Row.Cells(5).Value)
    
       'Ejecuta la consulta
       cmd.ExecuteNonQuery()
    Next

    Tercero, no es necesario cerrar la conexión ( con.Close() ) ya que al usar Using este cerrará la conexión y liberará el objeto usado.

    Como te comenté anteriormente, agrega un punto de interrupción y has seguimiento del código.

    Como no usas muchas columnas, en caso sigas con el mismo problema, puedes mostrar una imagen de los datos completos de tu DataGridView.

    Saludos.


    JC NaupaCrispín
    Lima - Perú

    La magia no existe, la programación SI

    viernes, 14 de octubre de 2016 2:22
  • Hola Joel C. Naupa Crispín

    Disculpa la tardanza en contestar, aún sigo con el mismo problema, no sé que estoy haciendo mal. Conoces algún tutorial sobre el uso de breakpoints?

    Saludos,


    lunes, 17 de octubre de 2016 22:30
  • Hola Juan Ortiz T,

    Puedes echarle un ojo al siguiente link :

    Depuración con Visual Studio: Puntos de interrupción condicionales

    Básicamente es crear un punto de interrupción en la parte de :

    Private Sub btnEditar_Click() ... '<--- Aquí
    .....
    ....
    ....
    End Sub '<-- Aquí

    Para que cuando se ejecute ese código comience. Usarías la tecla F10 para pasar de línea :

    - Muestro un ejemplo de un For, obtengo el valor por cada iteración.

    Saludos.


    JC NaupaCrispín
    Lima - Perú

    La magia no existe, la programación SI

    • Marcado como respuesta Juan Ortiz T jueves, 20 de octubre de 2016 1:50
    martes, 18 de octubre de 2016 3:44
  • Que tal Joel C. Naupa Crispín,

    Revise lo del uso de breakpoints y si me estaba pasando bien los valores, el detalle estaba en que usaba una misma clave para varios registros (filas) en ese tabla ya que necesito esos datos para usarlos como plantillas después, lo que hice fue crear un nuevo campo en mi tabla de Base de Datos en la cual cuento el número de filas, y a partir de ahí, tomo esa nuevo campo para modificar el número de fila deseado.

    Te agradezco el tiempo que te tomaste para ayudarme, y si me han servido tus respuestas.

    Éxito y de nuevo muchas gracias!

    Saludos


    jueves, 20 de octubre de 2016 1:16