Compartir a través de


Control de una excepción de simultaneidad en aplicaciones de base de datos de .NET Framework

Nota:

La DataSet clase y las clases relacionadas son tecnologías heredadas de .NET Framework de principios de los años 2000 que permiten a las aplicaciones trabajar con datos en memoria mientras las aplicaciones están desconectadas de la base de datos. Las tecnologías son especialmente útiles para las aplicaciones que permiten a los usuarios modificar datos y conservar los cambios de nuevo en la base de datos. Aunque los conjuntos de datos son una tecnología probada de éxito, el enfoque recomendado para las nuevas aplicaciones .NET es usar 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.

Las excepciones de simultaneidad (System.Data.DBConcurrencyException) se generan cuando dos usuarios intentan cambiar los mismos datos de una base de datos al mismo tiempo. En este tutorial, creará una aplicación de Windows que muestra cómo detectar un DBConcurrencyException, localizar la fila que provocó el error y aprender una estrategia para controlarlo.

Este tutorial le lleva a través del siguiente proceso:

  1. Cree un nuevo proyecto de aplicación Windows Forms (.NET Framework).

  2. Cree un nuevo conjunto de datos basado en la tabla Northwind Customers.

  3. Cree un formulario con un DataGridView para mostrar los datos.

  4. Rellene un conjunto de datos con datos de la tabla Customers en la base de datos Northwind.

  5. Use la característica Mostrar datos de tabla en el Explorador de servidores para acceder a los datos de la tabla Customers y cambiar un registro.

  6. Modifique el mismo registro a un valor diferente, actualice el conjunto de datos e intente escribir los cambios en la base de datos, lo que produce un error de concurrencia.

  7. Capture el error y, a continuación, muestre las distintas versiones del registro, lo que permite al usuario determinar si desea continuar y actualizar la base de datos o cancelar la actualización.

Prerrequisitos

En este tutorial se usa SQL Server Express LocalDB y la base de datos de ejemplo Northwind.

  1. Si no tiene SQL Server Express LocalDB, instálelo desde la página de descarga de SQL Server Express o mediante el Instalador de Visual Studio. En el instalador de Visual Studio , puede instalar SQL Server Express LocalDB como parte de la carga de trabajo de almacenamiento y procesamiento de datos , o como componente individual.

  2. Instale la base de datos de ejemplo Northwind siguiendo estos pasos:

    1. En Visual Studio, abra la ventana Explorador de objetos de SQL Server (El Explorador de objetos de SQL Server se instala como parte de la carga de trabajo Almacenamiento y procesamiento de datos en el Instalador de Visual Studio). Expanda el nodo SQL Server . Haga clic con el botón derecho en la instancia de LocalDB y seleccione Nueva consulta.

      Se abre una ventana del editor de consultas.

    2. Copie el script Northwind Transact-SQL en su Portapapeles. Este script de T-SQL crea la base de datos Northwind desde cero y la rellena con datos.

    3. Pegue el script T-SQL en el editor de consultas y, a continuación, elija el botón Ejecutar.

      Después de un breve tiempo, la consulta finaliza la ejecución y se crea la base de datos Northwind.

Creación de un nuevo proyecto

Comience creando una nueva aplicación de Windows Forms:

  1. En Visual Studio, en el menú Archivo , seleccione Nuevo>proyecto.

  2. Expanda Visual C# o Visual Basic en el panel izquierdo y, a continuación, seleccione Escritorio de Windows.

  3. En el panel central, seleccione el tipo de proyecto Aplicación de Windows Forms .

  4. Asigne al proyecto el nombre ConcurrencyWalkthrough y, a continuación, elija Aceptar.

    El proyecto ConcurrencyWalkthrough se crea y agrega al Explorador de soluciones y se abre un nuevo formulario en el diseñador.

Creación del conjunto de datos Northwind

A continuación, cree un conjunto de datos denominado NorthwindDataSet:

  1. En el menú Datos , elija Agregar nuevo origen de datos.

    Se abre el Asistente para configuración del origen de datos.

  2. En la pantalla Elegir un tipo de origen de datos , seleccione Base de datos.

    Asistente para configuración de orígenes de datos en Visual Studio

  3. Seleccione una conexión a la base de datos de ejemplo Northwind en la lista de conexiones disponibles. Si la conexión no está disponible en la lista de conexiones, seleccione Nueva conexión.

    Nota:

    Si se conecta a un archivo de base de datos local, seleccione No cuando se le pregunte si desea agregar el archivo al proyecto.

  4. En la pantalla Guardar cadena de conexión en el archivo de configuración de la aplicación , seleccione Siguiente.

  5. Expanda el nodo Tablas y seleccione la tabla Clientes . El nombre predeterminado del conjunto de datos debe ser NorthwindDataSet.

  6. Seleccione Finalizar para agregar el conjunto de datos al proyecto.

Creación de un control DataGridView enlazado a datos

En esta sección, creará un System.Windows.Forms.DataGridView al arrastrar el elemento Customers desde la ventana Orígenes de datos hacia su Formulario de Windows.

  1. Para abrir la ventana Orígenes de datos , en el menú Datos , elija Mostrar orígenes de datos.

  2. En la ventana Orígenes de datos , expanda el nodo NorthwindDataSet y, a continuación, seleccione la tabla Clientes .

  3. Seleccione la flecha hacia abajo en el nodo de tabla y, a continuación, seleccione DataGridView en la lista desplegable.

  4. Arrastre la tabla a un área vacía del formulario.

    Se agrega un control llamado CustomersDataGridView y un control llamado CustomersBindingNavigator al formulario que está enlazado a BindingSource. Esto es, a su vez, enlazado a la tabla Customers en NorthwindDataSet.

Probar el formulario

Ahora puede probar el formulario para asegurarse de que se comporta según lo previsto hasta este punto:

  1. Seleccione F5 para ejecutar la aplicación.

    El formulario aparece con un control DataGridView que está relleno con los datos de la tabla Customers.

  2. En el menú Depurar, seleccione Detener depuración.

Gestión de errores de concurrencia

La forma de controlar los errores depende de las reglas de negocio específicas que rigen la aplicación. Para este tutorial, usamos la siguiente estrategia como ejemplo para controlar el error de simultaneidad.

La aplicación presenta al usuario tres versiones del registro:

  • El registro actual de la base de datos

  • El registro original que se carga en el conjunto de datos

  • Cambios propuestos en el conjunto de datos

Después, el usuario puede sobrescribir la base de datos con la versión propuesta o cancelar la actualización y actualizar el conjunto de datos con los nuevos valores de la base de datos.

Para habilitar el manejo de errores de concurrencia

  1. Cree un controlador de errores personalizado.

  2. Mostrar opciones para el usuario.

  3. Procese la respuesta del usuario.

  4. Vuelva a enviar la actualización o restablezca los datos del conjunto de datos.

Adición de código para controlar la excepción de simultaneidad

Cuando intenta realizar una actualización y se genera una excepción, normalmente desea hacer algo con la información proporcionada por la excepción generada. En esta sección, agregará código que intenta actualizar la base de datos. También puede controlar cualquier DBConcurrencyException que se pueda generar, así como cualquier otra excepción.

Nota:

Los métodos CreateMessage y ProcessDialogResults se agregan más adelante en la guía paso a paso.

  1. Agregue el código siguiente debajo del Form1_Load método :

    private void UpdateDatabase()
    {
        try
        {
            this.customersTableAdapter.Update(this.northwindDataSet.Customers);
            MessageBox.Show("Update successful");
        }
        catch (DBConcurrencyException dbcx)
        {
            DialogResult response = MessageBox.Show(CreateMessage((NorthwindDataSet.CustomersRow)
                (dbcx.Row)), "Concurrency Exception", MessageBoxButtons.YesNo);
    
            ProcessDialogResult(response);
        }
        catch (Exception ex)
        {
            MessageBox.Show("An error was thrown while attempting to update the database.");
        }
    }
    

  1. Reemplace el CustomersBindingNavigatorSaveItem_Click método para llamar al UpdateDatabase método para que tenga el siguiente aspecto:

    private void customersBindingNavigatorSaveItem_Click(object sender, EventArgs e)
    {
        UpdateDatabase();
    }
    

Mostrar opciones para el usuario

El código que acaba de escribir llama al CreateMessage procedimiento para mostrar información de error al usuario. Para este tutorial, se usa un cuadro de mensaje para mostrar las distintas versiones del registro al usuario. Esto permite al usuario elegir si desea sobrescribir el registro con los cambios o cancelar la edición. Una vez que el usuario selecciona una opción (hace clic en un botón) en el cuadro de mensaje, la respuesta se pasa al ProcessDialogResult método .

Cree el mensaje agregando el código siguiente al Editor de código. Escriba este código debajo del UpdateDatabase método :

private string CreateMessage(NorthwindDataSet.CustomersRow cr)
{
    return
        "Database: " + GetRowData(GetCurrentRowInDB(cr), DataRowVersion.Default) + "\n" +
        "Original: " + GetRowData(cr, DataRowVersion.Original) + "\n" +
        "Proposed: " + GetRowData(cr, DataRowVersion.Current) + "\n" +
        "Do you still want to update the database with the proposed value?";
}


//--------------------------------------------------------------------------
// This method loads a temporary table with current records from the database
// and returns the current values from the row that caused the exception.
//--------------------------------------------------------------------------
private NorthwindDataSet.CustomersDataTable tempCustomersDataTable = 
    new NorthwindDataSet.CustomersDataTable();

private NorthwindDataSet.CustomersRow GetCurrentRowInDB(NorthwindDataSet.CustomersRow RowWithError)
{
    this.customersTableAdapter.Fill(tempCustomersDataTable);

    NorthwindDataSet.CustomersRow currentRowInDb = 
        tempCustomersDataTable.FindByCustomerID(RowWithError.CustomerID);

    return currentRowInDb;
}


//--------------------------------------------------------------------------
// This method takes a CustomersRow and RowVersion 
// and returns a string of column values to display to the user.
//--------------------------------------------------------------------------
private string GetRowData(NorthwindDataSet.CustomersRow custRow, DataRowVersion RowVersion)
{
    string rowData = "";

    for (int i = 0; i < custRow.ItemArray.Length ; i++ )
    {
        rowData = rowData + custRow[i, RowVersion].ToString() + " ";
    }
    return rowData;
}

Procesar la respuesta del usuario

También necesita código para procesar la respuesta del usuario al cuadro de mensaje. Las opciones son sobrescribir el registro actual de la base de datos con el cambio propuesto, o abandonar los cambios locales y actualizar la tabla de datos con el registro que se encuentra actualmente en la base de datos. Si el usuario elige Sí, se llama al Merge método con el argumento preserveChanges establecido en true. Esto provoca que el intento de actualización sea exitoso, ya que ahora la versión original del registro coincide con el registro en la base de datos.

Agregue el código siguiente debajo del código que se agregó en la sección anterior:

// This method takes the DialogResult selected by the user and updates the database 
// with the new values or cancels the update and resets the Customers table 
// (in the dataset) with the values currently in the database.

private void ProcessDialogResult(DialogResult response)
{
    switch (response)
    {
        case DialogResult.Yes:
            northwindDataSet.Merge(tempCustomersDataTable, true, MissingSchemaAction.Ignore);
            UpdateDatabase();
            break;

        case DialogResult.No:
            northwindDataSet.Merge(tempCustomersDataTable);
            MessageBox.Show("Update cancelled");
            break;
    }
}

Probar el comportamiento del formulario

Ahora puede probar el formulario para asegurarse de que se comporta según lo previsto. Para simular una infracción de simultaneidad, cambie los datos de la base de datos después de rellenar NorthwindDataSet.

  1. Seleccione F5 para ejecutar la aplicación.

  2. Una vez que aparezca el formulario, déjelo en ejecución y cambie al IDE de Visual Studio.

  3. En el menú Ver , elija Explorador de servidores.

  4. En el Explorador de servidores, expanda la conexión que usa la aplicación y, a continuación, expanda el nodo Tablas .

  5. Haga clic con el botón derecho en la tabla Clientes y, a continuación, seleccione Mostrar datos de tabla.

  6. En el primer registro (ALFKI), cambie ContactName a Maria Anders2.

    Nota:

    Vaya a otra fila para confirmar el cambio.

  7. Cambie al formulario activo de ConcurrencyWalkthrough.

  8. En el primer registro del formulario (ALFKI), cambie ContactName a Maria Anders1.

  9. Selecciona el botón Guardar.

    Se produce el error de simultaneidad y aparece el cuadro de mensaje.

    Al seleccionar No se cancela la actualización y se actualiza el conjunto de datos con los valores que se encuentran actualmente en la base de datos. Al seleccionar Sí, se escribe el valor propuesto en la base de datos.