none
Como puedo guardar datos de un dataset editado a la base de datos

    Pregunta

  • hago algo así:

    Tengo la tabla clientes que entre sus campos pongo el numero del cliente, (como un índice), hoy puede estar en lugar 6, pero después del proceso el usuario podría pasar al lugar 7 (es decir, que el dato en ese campo cambia de numero 6 a numero 7) dentro de la lista y así sucesivamente con los demás, así que realizo esos cambios en el dataset donde tengo la consulta, ¿Cómo hago para llevar esos cambios a mi base de datos en el servidor? o alguna idea de cómo cambiar dinámicamente los datos contenidos en ese campo que hace las veces de índice para organizar la posición de los clientes?

    de antemano, muchas gracias por el tiempo dedicado y la información suministrada.

    lunes, 6 de marzo de 2017 1:28

Respuestas

  • En lineas generales, lo que aprecio es poco dominio de ADO.NET, como por ejemplo en el doble llenado del datatable independiente y el datatable del dataset, cuando es sencillísimo sacar o meter un datatable de un dataset, por lo que no se necesita duplicarlo. O la repetición de la llamada al Dispose (una vez en el finally y otra vez fuera del bloque try). Esto puede ocasionar problemas con algunos objetos, que no admiten llamar dos veces al Dispose. No digo que en tu caso concreto esto ocasione ningún problema en particular, simplemente es un ejemplo más de cosas que no están muy "finas" en tu programa.

    Yo recomendaría, en lugar de escribir un programa grandote que acumule media docena de errores, ir probando y ejercitando cada función una por una en una rutinita pequeña que haga únicamente esa función. Si algo no funciona como esperabas, no te quedes tan tranquilo y busques una alternativa ("he tenido problemas para sacar información de la consulta y ponerla desde el dataset a un textbox o label, así que lo hago con el dataTable"). Investiga por qué las cosas no funcionan como esperabas que funcionasen, porque lo contrario implica una laguna en los conocimientos que más adelante te podría ocasionar errores en otro sitio. Según vayas teniendo dominada cada parte, entonces ya velas juntando en un programa más amplio que las combine todas a la vez. Y si algo no funciona, utiliza el debugger. Sigue el código paso a paso y examina las variables en cada punto, hasta donde encuentres algo que no funcione como esperabas que funcionase. Y cuando eso suceda, no te limites a buscar una alternativa; cerciórate de que comprendes por qué el programa estaba haciendo lo que hacía, en lugar de lo que pensabas que debería hacer.

    • Marcado como respuesta Dzea domingo, 12 de marzo de 2017 17:04
    domingo, 12 de marzo de 2017 16:02

Todas las respuestas

  • Si el dataset lo trajiste desde la base de datos usando un dataadapter (método Fill), y el dataadapter está bien configurado, entonces después de hacer los cambios en el dataset lo puedes volver a salvar llamando al método .Update del dataadapter.

    El inconveniente que te puedes encontrar es que si el campo que estás cambiando tiene una restricción de unicidad, se producirán errores al grabar. Por ejemplo, si el cliente 6 lo has cambiado a 7 y el 7 ya existe, te daría un error. Cierto que el 7 lo vas a cambiar a 8 y así sucesivamente, pero en el momento de cambiar 6 por 7 el 7 todavía existe y por tanto fallará ese Update. El remedio más sencillo, si el cambio siempre va a ser creciente, es actualizarlos al revés, es decir, empezando por el último. Para ello puedes ponerle un "order by numero DESC" al cargar el dataset, para que contenga los datos en orden inverso. Si tu caso es más complejo, y los cambios se pueden hacer en cualquier orden, plantéalo aquí y buscaremos otras soluciones.

    lunes, 6 de marzo de 2017 7:46
  • Gracias, por la pronta respuesta!!

    bueno, me asalta una pregunta... a que te refieres con un "DataAdapter" bien configurado, éste el trozo de código donde lleno mi DataAdapter y lo pongo en un DataSet y en un DataTablet.

    Private Scon As New MySqlCommand
    Private Dadp As New MySqlDataAdapter
    Protected Friend Dset As New DataSet()
    Protected Friend DTable As New DataTable
    Friend Kcon As New MySqlConnection(Kdb)
    
    Scon.Connection = Kcon 
    Scon.CommandText = Ssql
    Dadp.SelectCommand = Scon
    
            Try
    
                Dadp.Fill(DTable)
                Dadp.Fill(Dset, Stable)

    ahora, el campo donde va este orden de clientes no le puse ninguna restricción para evitarme complicaciones adicionales, sin embargo tengo problemas para trabajar en local que es lo que quiero hacer, ya que según yo, tengo la consulta en el dataset y cuando intento recorrerlo me sale un error, aún cuando hago pruebas de descargarlo en un datagridview antes de recorrerlo

    este es el código con el que intento recorrer el dataset :'(

     Dim sql As String = 
               "select * from customer order by  indexID ASC"
    db.Search(sql, "Customers") 'aquí envío mi consulta
    
    Dim lugar As Integer = Integer.Parse(txtLugar.Text)
    
    Dim Mitabla as DataRow=db.Dset.Tables("Customers").Select("indexID")
    For Each rw As DataRow In Mitabla
    rw.Item("indexID") = lugar + 2
    'estoy intentando sumar dos a index en todas las posiciones
    'para hacer la prueba de recorrer el dataset
    Next
    
    DataGridView1.DataSource = db.Dset.Tables("Customers")
    DataGridView1.Refresh()

    el error es: Message=Referencia a objeto no establecida como instancia de un objeto.

    mi idea es, ubicarme en la fila donde está la posición del nuevo cliente y desde allí empezar a aumentar de 1 en 1 el valor de ese campo, una vez termine, agrego el dato del cliente y su posición. ya habiendo hecho eso, enviar la tabla con un único "insert to". ¿porque quiero hacerlo así y no directamente al servidor? porque estos listados tienden a tener unos 200 a 500 clientes y puedo tener 50 tablas diferentes con esa cantidad de clientes y hacer un update significaría hacer esa misma cantidad de transacciones y si la cantidad de usuarios son 10, tendré un flujo de 200 a 500 *10 transacciones al servidor, y creo que sería contraproducente, además de una "mala praxis"

    espero haber esclarecido aún más el tema y veas las falencias que tengo con respecto a esto

    de nuevo gracias por tu tiempo y por brindarme de tu conocimiento!!

    sábado, 11 de marzo de 2017 6:44
  • A ver, me hago un poco un lío.¿Cuál de los dos métodos estás usando? ¿El que pusiste en el primer bloque? En ese caso, la carga que haces de los datos hacia el dataset debería de funcionar, suponiendo que Ssql tenga una sentencia corecta.

    Por cierto, tienes duplicado el Fill: primero lo usas para llenar un datatable, y luego lo vuelves a usar para llenar otro datatable dentro de un dataset. Una de las dos cosas sobra.

    Pero con ese dataadapter que has configurado de esa manera no podrás usar el Update como yo te proponía en la respuesta anterior. Por eso yo decía "si el dataadapter está bien configurado". En este caso lo has configurado en solo-lectura (porque únicamente tiene el SelectCommand), así que no podrás grabar porque no has asignado los otros commands (insert, update, delete). Si no quieres escribirlos todos uno por uno, suguero usar un CommandBuilder para que los asigne automáticamente.

    Y luego llegas a la segunda parte donde dices "este es el código con el que intento recorrer el dataset". Ahí manejas un objeto "db" que no se sabe lo que es ni cómo lo has inicializado (y desde luego en algún sitio falta inicializar algo porque te sale el error de "Referencia a objeto no establecida"). No puede ser un DataSet, porque el dataset no admite pasarle una sentencia Select al método Search.
    Y luego abajo llamas a db.Dset.Tables("Customers"), que no se ve dónde se ha inicializado pero que devolverá Nothing (y por tanto dará error de Referencia no establecida) si en las tablas de Dset no hay ninguna que tenga el nombre "Customers" (ojo, hay que asignárselo al cargar la tabla, no lo toma de la Select). Y luego haces .Select("indexID"). Esto buscaría la palabra "IndexID" dentro de la clave primaria del datatable, si es que lo has cargado con clave primaria, sino dará un error. El resultado solo puede ser una única fila (DataRow), porque la clave primaria no admite duplicados. Pero ese datarow lo llamas "MiTabla" y lo intentas recorrer con un bucle, como si fueran varias filas, cosa que no puede funcionar.

    sábado, 11 de marzo de 2017 8:46
  • Hola, gracias por responder, empezaré por responderte todo:

    tengo una clase llamada conexionDB donde tengo (valga la redundancia), la conexion a la base de datos, ahora "db" la inicializo en el form donde usaré los métodos que tengo en la clase conexiónDB, la pongo así. Dim db as new conexionDB().

    Ssql trae en sentencia con la consulta. ejemplo "select * from customers", el porque se llena un dataTable y luego un dataset? bueno, he tenido problemas para sacar información de la consulta y ponerla desde el dataset a un textbox o label, así que lo hago con el dataTable; el dataset, lo uso para llenar combobox y datagridview's (Pero tienes razón, buscaré la manera de eliminar DTable y sólo usar Dset). a continuación te pongo el método completo "Search"

     
    Private Scon As New MySqlCommand
    Private Dadp As New MySqlDataAdapter
    Protected Friend Dset As New DataSet()
    Protected Friend DTable As New DataTable
    Friend Kcon As New MySqlConnection(Kdb) 'kdb trae la sentencia para conectarse a la DB

    Public Sub Search(Ssql As String, Stable As String) Dset.Tables.Clear() ' Borramos las tablas Guardadas DTable.Rows.Clear() ' Borramos las filas DTable.Columns.Clear() ' Borramos las Columnas DTable.Reset() 'Reiniciamos la tabla Dset.Clear() ' Borramos el DataSet Kcon.Open() Scon.Connection = Kcon ' Luego le pasamos la conexión al MySqlCommand Scon.CommandText = Ssql ' Le entregamos la consulta Sql Dadp.SelectCommand = Scon ' Luego le pasamos la consulta al DataAdapter Try Dadp.Fill(DTable) Dadp.Fill(Dset, Stable) Catch sqlerror As MySqlException Wrong = "Error: " & sqlerror.Message 'wrong es una variable publica que uso para llevar

    'el error a donde he llamado el método "search" Finally Kcon.Close() Kcon.Dispose() End Try Kcon.Close() Kcon.Dispose() End Sub

    en cuanto al error (Referencia a objeto no establecida), encontré, que en la sentencia llamaba a la tabla "customer", cuando en realidad se llama "customers" con "s" al final. sin embargo aun después de eso seguía fallando y con tu explicación me queda más que claro el porqué.

    y bueno en vista de que es un intento mega fallido, me encuentro en punto muerto con respecto al tema, así que estoy abierto a cualquier sugerencia, si es necesario cambiar todo el código, la manera de conectarse a la DB, eliminar el método, etc. sólo dime en dónde buscar, qué buscar, algún link o sugerencia de código.

    nuevamente agradezco tu tiempo y detalladas observaciones.

    domingo, 12 de marzo de 2017 9:32
  • En lineas generales, lo que aprecio es poco dominio de ADO.NET, como por ejemplo en el doble llenado del datatable independiente y el datatable del dataset, cuando es sencillísimo sacar o meter un datatable de un dataset, por lo que no se necesita duplicarlo. O la repetición de la llamada al Dispose (una vez en el finally y otra vez fuera del bloque try). Esto puede ocasionar problemas con algunos objetos, que no admiten llamar dos veces al Dispose. No digo que en tu caso concreto esto ocasione ningún problema en particular, simplemente es un ejemplo más de cosas que no están muy "finas" en tu programa.

    Yo recomendaría, en lugar de escribir un programa grandote que acumule media docena de errores, ir probando y ejercitando cada función una por una en una rutinita pequeña que haga únicamente esa función. Si algo no funciona como esperabas, no te quedes tan tranquilo y busques una alternativa ("he tenido problemas para sacar información de la consulta y ponerla desde el dataset a un textbox o label, así que lo hago con el dataTable"). Investiga por qué las cosas no funcionan como esperabas que funcionasen, porque lo contrario implica una laguna en los conocimientos que más adelante te podría ocasionar errores en otro sitio. Según vayas teniendo dominada cada parte, entonces ya velas juntando en un programa más amplio que las combine todas a la vez. Y si algo no funciona, utiliza el debugger. Sigue el código paso a paso y examina las variables en cada punto, hasta donde encuentres algo que no funcione como esperabas que funcionase. Y cuando eso suceda, no te limites a buscar una alternativa; cerciórate de que comprendes por qué el programa estaba haciendo lo que hacía, en lugar de lo que pensabas que debería hacer.

    • Marcado como respuesta Dzea domingo, 12 de marzo de 2017 17:04
    domingo, 12 de marzo de 2017 16:02
  • eso haré!! gracias por el consejo
    domingo, 12 de marzo de 2017 16:23