Actualizar dos tablas vinculadas en una vista Maestro-Detalle

Una de las consultas comúnmente solicitadas a través del Blog, tiene que ver con la actualización de datos de dos tablas relacionadas en una BD de SQL, o sea actualizar una vista maestro-detalle vinculadas a sendas tablas.

Aunque por obvio y sencillo, las explicaciones acostumbran a ser de lo más diversas y finalmente te das cuenta que la mayoría de ejemplos se inician con un “desparrame” de jergas incomprensivas para la mayoría. Me decido postearos el ejemplo más básico posible, para que a partir de este punto podáis hacerlo crecer a vuestra necesidad.

Espero que os sea útil y despeje vuestras jaquecas cuando se trata de lidiar con diversas tablas.
PepLluis,

 (Para ejecutar el ejemplo, iniciar Visual Studio y crear un nuevo proyecto ‘Winform’, añadir dos DataGridView y un Button, copiar / pegar codigo y por supuesto F5)

Imports System.Data.SqlClient

Public Class Form1

    Private Maestro As SqlDataAdapter
    Private Detalle As SqlDataAdapter
    Private ConjuntoDeDatos As DataSet

    Private Sub Form1_Load() Handles MyBase.Load

        Dim miConexion As New SqlConnection("Data Source=.\SQLExpress;Initial Catalog=MaestroDetalle;Integrated Security=True")

        Maestro = New SqlDataAdapter("Select * From Maestro", miConexion)
        Dim MaestroCmdBuilder As New SqlCommandBuilder(Maestro)

        Detalle = New SqlDataAdapter("Select * From Detalle", miConexion)
        Dim DetalleCmdBuilder As New SqlCommandBuilder(Detalle)

        ConjuntoDeDatos = New DataSet
        Maestro.Fill(ConjuntoDeDatos, "Maestro")
        Me.DataGridView1.DataSource = ConjuntoDeDatos
        Me.DataGridView1.DataMember = "Maestro"

        Detalle.Fill(ConjuntoDeDatos, "Detalle")
        Me.DataGridView2.DataSource = ConjuntoDeDatos

        ConjuntoDeDatos.Relations.Add("Fk", ConjuntoDeDatos.Tables("Maestro").Columns("IdMaestro"),
                                            ConjuntoDeDatos.Tables("Detalle").Columns("IdDetalle"))

        Me.DataGridView2.DataMember = "Maestro.Fk"
    End Sub

    Private Sub Actualizar() Handles Button1.Click
        If ConjuntoDeDatos.HasChanges Then
            Maestro.Update(ConjuntoDeDatos, "Maestro")
            Detalle.Update(ConjuntoDeDatos, "Detalle")
        End If
    End Sub
End Class

19 Replies to “Actualizar dos tablas vinculadas en una vista Maestro-Detalle”

  1. Hi Bunbala,
    Problably you have a problem with keys, you must verify and define the primary keys in every table.
    Please give the message error or contact with me to explain better and continue this conversation.

    Regards,
    Pep Lluis,

  2. thanks for your reply, i think i define the primary keys correctly, the error message is: “The UPDATE statement conflicted with the REFERENCE constraint “FK_Detail_Master”. The conflict occurred in database “MasterDetail”, table “dbo.Detail”, column ‘m_id’. The statement has been terminated.”

    or you can download the code and data from this link: http://rapidshare.com/files/416416242/bumbala.zip

  3. Bunbala,

    Your m_id in detail used as relation is defined for “allow null values”, try with uncheck allow option.

    Regards,

    Pep Lluis,

  4. Hola, hacer esto así, con dos DataGrid es sencillo, lo complicado está en hacerlo cuando muestras datos del maestro y detalle en el mismo DataGrid. ¿Tienes algún ejemplo de ello? Gracias de antemano.

  5. Hola Ivan,
    Este blog intenta ayudar con ejemplos sencillos, tambien dependiendo del tema de interes publicamos alguno que otro mas complejo, pero lamentablemente no dispongo en estos momentos de ninguno como el que necesitas. Has probado en lanzar esta peticion en los foros de MSDN, seguro que alguien ya ha tratado el tema con anterioridad.

    Saludos,
    Pep Lluis,

  6. Hola Pep, ¿qué tal? Buscando por Google, acabo de encontrarme con este post tuyo y me parece muy bueno.

    El caso es que necesito hacer algo similar, pero me gustaría ampliar en varias cosas y me he atrevido a solicitarte ayuda, por supuesto, si tienes disponibilidad y te parece bien prestármela. Es lo siguiente:
    – Me gustaría permitir que el usuario modificase, añadiese y eliminara registros directamente en los datagridview… ¿Con qué eventos puedo controlar que los datos cumplan las restricciones oportunas, así como acciones posteriores a la actualización de un registro, etc…?
    – Para un entorno multiusuario, ¿es posible gestionar la concurrencia con esa edición directa en los grid? ¿Puedes orientarme cómo hacerlo?
    – Me gustaría usar modo desconectado (así me basta con las 5 conexiones de SQL Express), pero no sé si los dataadapter abren y cierran la conexión cuando la usan o la mantienen abierta todo el tiempo que están instanciados. ¿Puedes orientarme?

    Muchas gracias por adelantado, como he dicho antes, entenderé que no puedas ayudarme… hoy en día todos vamos algo estresados.

    Saludos
    David Montesa

  7. Hola David,
    Para responderte rapido, pues quizas es mas apropiado postear estas preguntas/respuestas en los foros para que sean utiles a otras personas.

    – Los adaptadores siempre funcionan en modo desconectado.
    – Tiempo atras tenia un ejemplo para controlar concurrencia… pero no dispongo de tiempo para componerlo.

    Si te parece y lo necesitas contactame directamente o pasamos a los foros para postear algo sobre concurrencia.

    Saludos,
    PepLluis,

  8. Hola Pep:
    Gracias por el post,Tengo un problema, y es que no me carga el segundo Datagrid, he utilizado una base en la que tengo clientes(esos ls carga sin problema)y codigos postales ya enlazada en mysql,en la relación, los hago por campo común, lo único que se me ocurre es que tengo 3 campos en la tabla de codigos postales, y por eso no los carga,si me echaras una mano te lo agradecería, y si no ,pues también.
    un saludo

  9. Muchas gracias por tu aportacion, segui el ejemplo que esta posteado adaptado ami base de datos de acces y funciona bien pero el momento de guardar los cambios que hago en el Datagridvie “Detalle” me marca eror:
    “La generación SQL dinámica para UpdateCommand no es compatible con SelectCommand, que no devuelve ninguna información sobre columnas clave.” Me puede ayudar que se deba este eror..? gracias

  10. Hola Juan Carlos,
    Según la información que incluyes y a simple vista te estaria indicando que debes tener bien definida las “claves primarias” es por eso que el “commandbuilder” no puede completar la generación dinamica del “UpdateCommand”.

    Espero que esto te ayude.
    PepLluis,

  11. Muy bueno y sencillo tu ejemplo, sin las complicaciones de otros que se encuentran en la red.
    Por otra parte te hago un a consulta: cuando cambio de fila en el maestro con el raton o teclado, el detalle se me actualiza sin problema, pero si cambio la selección por código no no se actualiza el detalle (busco un determinado valor en la grilla maestra y si lo encuentra la establesco como fila actual con .select)¿cómo debería hacer para que me funcione? Gracias.

  12. Hola PepLluis Navegando por la red encontre su página, y es que tengo un problema similar, estoy programando Microsoft Visual Studio 2008 Professional.

    Tengo dos tablas en la misma base PagosClientes.accdb, una llamada Clientes con 22 campos y otra llamada PagosCliente con 47 campos entre ellas hay tres campos en común; IdReg, Cta, Nombre :Clientes esta relacionada con un BindingNavigator y un DataGredview funciona perfecto por medio del campo IdReg, la PagosClientes Se reflejan los datos en textbox con una busqueda FillByToolStrip y funciona perfectamente por medio del campo Cta.

    La pregunta es:

    Como o que puedo hacer para que funcionen o se relacionen por un mismo campo en comun ya sea el IdReg o el Cta.

    Aclaro que estoy aprendiendo a programar asi que de conocimientos en programacion estoy un poco atrazado

    Se Agradece de antemano la ayuda que me pueda brindar.

    Atentamente Jose Luis C.

  13. Hola Pepe Luis,
    En primer lugar te animaría a postear en los foros, pues podremos contestar mayor numero de personas y también se beneficiaran los que tengan las mismas dudas.

    No se si responde a tu pregunta, pero en principio deberías poder resolverlo con ‘relations’ i/o binding… mira este otro ejemplo :
    http://msmvps.com/blogs/peplluis/archive/2009/03/23/como-enlazar-columnas-de-una-tabla-sql-a-unos-textbox.aspx

    En otro caso, contáctame directamente.. opción [contact] con un poco del código a revisar.

    Saludos,
    PepLluis,

Leave a Reply to peplluis Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.