Share via


Actualización jerárquica en el desarrollo de .NET Framework

Nota:

Los conjuntos de datos y las clases relacionadas son tecnologías heredadas de .NET Framework de principios de la década de 2000 que permiten a las aplicaciones trabajar con datos en memoria mientras están desconectadas de la base de datos. Son especialmente útiles para las aplicaciones que permiten a los usuarios modificar los datos y conservar los cambios en la base de datos. Aunque los conjuntos de datos han demostrado ser una tecnología de gran éxito, se recomienda que las nuevas aplicaciones de .NET usen Entity Framework Core. Entity Framework proporciona una manera más natural de trabajar con datos tabulares como modelos de objetos y tiene una interfaz de programación más sencilla.

La actualización jerárquica hace referencia al proceso de guardar los datos actualizados (de un conjunto de datos con dos o más tablas relacionadas) en una base de datos al tiempo que se mantienen las reglas de integridad referencial. La integridad referencial hace referencia a las reglas de coherencia proporcionadas por las restricciones de una base de datos que controlan el comportamiento de inserción, actualización y eliminación de registros relacionados. Por ejemplo, es una integridad referencial la que exige la creación de un registro de cliente antes de permitir que los pedidos se creen para ese cliente. Para más información sobre las relaciones de los conjuntos de datos, consulte Relaciones en conjuntos de datos.

La característica de actualización jerárquica usa un TableAdapterManager para administrar los TableAdapter de un conjunto de datos con tipo. El componente TableAdapterManager es una clase generada por Visual Studio, no un tipo de .NET. Al arrastrar una tabla desde la ventana Orígenes de datos a una página de Windows Form o WPF, Visual Studio agrega una variable de tipo TableAdapterManager al formulario o página y esta la puede ver en el diseñador en la bandeja de componentes. Para obtener información detallada sobre la clase TableAdapterManager, consulte la sección Referencia de TableAdapterManager de TableAdapters.

De forma predeterminada, un conjunto de datos trata las tablas relacionadas como "solo relaciones", lo que significa que no se aplican restricciones de clave externa. Puede modificar esa configuración durante el tiempo de diseño mediante el Diseñador de DataSet. Seleccione la línea de relación entre dos tablas para abrir el cuadro de diálogo Relación. Los cambios que realice aquí determinarán cómo se comporta TableAdapterManager cuando envíe los cambios de las tablas relacionadas de nuevo a la base de datos.

Habilitar la actualización jerárquica en un conjunto de datos

De forma predeterminada, la actualización jerárquica está habilitada para todos los nuevos conjuntos de datos que se agregan o se crean en un proyecto. Active o desactive la actualización jerárquica estableciendo la propiedad Actualización jerárquica de un conjunto de datos con tipo del conjunto de datos en True o False:

Configuración de la actualización jerárquica

Creación de una nueva relación entre tablas

Para crear una nueva relación entre dos tablas, en el Diseñador de DataSet, seleccione la barra de título de cada tabla y, a continuación, haga clic con el botón derecho y seleccione Agregar relación.

Menú Agregar relación de una actualización jerárquica

Descripción de las restricciones FOREIGN KEY y actualizaciones en cascada y eliminaciones

Es importante saber cómo se crean las restricciones FOREIGN KEY y el comportamiento en cascada en la base de datos en el código del conjunto de datos generado.

De forma predeterminada, las tablas de datos en un conjunto de datos se generan con relaciones (DataRelation) que coinciden con las relaciones en la base de datos. Sin embargo, la relación en el conjunto de datos no se genera como una restricción FOREIGN KEY. DataRelation se configura como Solo relación sin UpdateRule o DeleteRule en vigor.

De forma predeterminada, las actualizaciones y las eliminaciones en cascada están desactivadas, incluso si la relación de la base de datos establece que estén activadas. Por ejemplo, al crear un nuevo cliente y un nuevo pedido, e intentar a continuación guardar los datos, se puede producir un conflicto con las restricciones FOREIGN KEY que se definen en la base de datos. Para más información, consulte Desactivar restricciones al llenar un conjunto de datos.

Establecer el orden para realizar las actualizaciones

Al establecer el orden para realizar actualizaciones se establece el orden de las inserciones, actualizaciones y eliminaciones individuales exigido para guardar todos los datos modificados en todas las tablas de un conjunto de datos. Cuando la actualización jerárquica está habilitada, primero se realizan las inserciones, después las actualizaciones y, por último, las eliminaciones. TableAdapterManager proporciona una propiedad UpdateOrder que se puede establecer para realizar primero las actualizaciones, después las inserciones y, por último, las eliminaciones.

Nota:

Es importante entender que el orden de actualización incluye todo. Es decir, cuando se realizan las actualizaciones, se realizan las inserciones y, posteriormente, las eliminaciones en todas las tablas del conjunto de datos.

Para establecer la propiedad UpdateOrder, después de arrastrar los elementos de la ventana Orígenes de datos a un formulario, seleccione TableAdapterManager en la bandeja de componentes y establezca la propiedad UpdateOrder en la ventana Propiedades.

Creación de una copia de seguridad de un conjunto de datos antes de realizar una actualización jerárquica

Cuando se guardan datos (llamando al método TableAdapterManager.UpdateAll() ), TableAdapterManager intenta actualizar los datos para cada tabla en una transacción única. Si se produce un error en cualquier parte de la actualización en cualquier tabla, se revierte la transacción entera. En la mayoría de las situaciones, la reversión devuelve la aplicación a su estado original.

Sin embargo, a veces se decide restaurar el conjunto de datos a partir de la copia de seguridad. Un ejemplo de esto puede ocurrir cuando se usan valores de incremento automático. Por ejemplo, si el proceso de guardar la operación no es correcto, los valores de incremento automático no se restablecen en el conjunto de datos y el conjunto de datos continuará creando valores de incremento automático. Esto deja un vacío en la numeración que puede que la aplicación no admita. En situaciones donde éste es un problema, TableAdapterManager proporciona una propiedad BackupDataSetBeforeUpdate que reemplaza el conjunto de datos existente con una copia de seguridad si se produce un error en la transacción.

Nota

La copia de seguridad solo está en memoria mientras se ejecuta el método TableAdapterManager.UpdateAll. Por consiguiente, no habrá acceso mediante programación a esta copia de seguridad del conjunto de datos porque, o bien reemplaza el conjunto de datos original, o se queda fuera del ámbito en cuanto el método TableAdapterManager.UpdateAll termina de ejecutarse.

Modificación del código de guardado generado para realizar la actualización jerárquica

Guarde en la base de datos los cambios de las tablas de datos relacionadas del conjunto de datos; para ello, llame al método TableAdapterManager.UpdateAll y pase el nombre del conjunto de datos que contiene las tablas relacionadas. Por ejemplo, ejecute el método TableAdapterManager.UpdateAll(NorthwindDataset) para enviar las actualizaciones de todas las tablas de NorthwindDataset a la base de datos back-end.

Después de colocar en los elementos de la ventana Orígenes de datos, el código se agrega automáticamente al evento Form_Load para rellenar cada tabla (los métodos TableAdapter.Fill). También se agrega código al evento de clic del botón Guardar del BindingNavigator para guardar los datos desde el conjunto de datos de nuevo a la base de datos (el método TableAdapterManager.UpdateAll).

El código de guardado generado también contiene una línea de código que llama al método CustomersBindingSource.EndEdit. Más concretamente, llama al método EndEdit del primer BindingSource que se agregó al formulario. En otras palabras, el código solo se genera para la primera tabla que se arrastra desde la ventana Orígenes de datos al formulario. La llamada EndEdit confirma los cambios que están en curso en los controles enlazados a datos que se estén editando en ese momento. Por lo tanto, si un control enlazado a datos aún tiene el foco y hace clic en el botón Guardar, todas las ediciones pendientes en ese control se confirman antes del guardado real (el método TableAdapterManager.UpdateAll).

Nota:

El Diseñador de DataSet solo agrega el código BindingSource.EndEdit para la primera tabla que se coloca en el formulario. Por lo tanto, tiene que agregar una línea de código para llamar al método BindingSource.EndEdit para cada tabla relacionada en el formulario. Para este tutorial, esto significa que tiene que agregar una llamada al método OrdersBindingSource.EndEdit.

  1. Haga doble clic en el botón Guardar, en el BindingNavigator, para abrir Form1 en el Editor de código.

  2. Agregue una línea de código para llamar al método OrdersBindingSource.EndEdit después de la línea que llama al método CustomersBindingSource.EndEdit. El código del evento de clic del botón Guardar debe tener un aspecto similar al siguiente:

    this.Validate();
    this.customersBindingSource.EndEdit();
    this.ordersBindingSource.EndEdit();
    this.tableAdapterManager.UpdateAll(this.northwindDataSet);
    

Además de confirmar los cambios en una tabla secundaria relacionada antes de guardar los datos en una base de datos, quizás también tenga que confirmar los registros primarios recién creados antes de agregar nuevos registros secundarios a un conjunto de datos. En otras palabras, quizás tenga que agregar el nuevo registro primario (Customer) al conjunto de datos para que las restricciones de clave externa permitan agregar nuevos registros secundarios (Orders) al conjunto de datos. Para ello, puede usar el evento BindingSource.AddingNew secundario.

Nota:

Que tenga que confirmar los nuevos registros primarios o no depende del tipo de control que se use para enlazar al origen de datos. En este tutorial, se usan controles individuales para enlazar a la tabla primaria. Esto requiere el código adicional para confirmar el nuevo registro primario. Si, en vez de eso, los registros primarios se mostraron en un control de enlace complejo, como DataGridView, esta llamada adicional a EndEdit para el registro primario no sería necesaria. Esto se debe a que la funcionalidad de enlace a datos subyacente del control controla la confirmación de los nuevos registros.

Para agregar código para confirmar los registros primarios en el conjunto de datos antes de agregar registros secundarios

  1. Cree un controlador para el evento OrdersBindingSource.AddingNew.

    • Abra Form1 en la vista de diseño, seleccione OrdersBindingSource en la bandeja de componentes, seleccione Eventos en la ventana Propiedades y, después, haga doble clic en el evento AddingNew.
  2. Agregue al controlador de eventos una línea de código que llame al método CustomersBindingSource.EndEdit. El código del controlador de evento OrdersBindingSource_AddingNew debe tener un aspecto similar al siguiente:

    this.customersBindingSource.EndEdit();
    

Referencia de TableAdapterManager

De forma predeterminada, se genera una clase TableAdapterManager cuando se crea un conjunto de datos que contiene tablas relacionadas. Para evitar que se genere la clase, cambie el valor de la propiedad Hierarchical Update del conjunto de datos a false. Al arrastrar una tabla que tiene una relación por la superficie de diseño de una página de Windows Form o WPF, Visual Studio declara una variable miembro de la clase. Si no usa el enlace de datos, debe declarar manualmente la variable.

La clase TableAdapterManager no es un tipo de .NET. Por lo tanto, no puede buscarlo en la documentación. Se crea en tiempo de diseño como parte del proceso de creación del conjunto de datos.

A continuación, se muestran los métodos y propiedades usados con frecuencia de la clase TableAdapterManager:

Miembro Descripción
Método UpdateAll Guarda todos los datos de todas las tablas de datos.
Propiedad BackUpDataSetBeforeUpdate Determina si se va a crear una copia de seguridad del conjunto de datos antes de ejecutar el método TableAdapterManager.UpdateAll.
Propiedad tableNameTableAdapter Representa un objeto TableAdapter. El objeto generado TableAdapterManager contiene una propiedad para cada objeto TableAdapter que administra. Por ejemplo, se genera un conjunto de datos con una tabla Clientes y pedidos con un objeto TableAdapterManager que contiene las propiedades CustomersTableAdapter y OrdersTableAdapter.
Propiedad UpdateOrder Controla el orden de los comandos individuales de inserción, actualización y eliminación. Establezca esta propiedad en uno de los valores de la enumeración TableAdapterManager.UpdateOrderOption.

De forma predeterminada, UpdateOrder se establece en InsertUpdateDelete. Esto significa que las inserciones, las actualizaciones y las eliminaciones se realizan para todas las tablas del conjunto de datos.