Número 50julio-AGOSTO 2008

Visual Basic•C#•ASP.NET•ADO.NET•AJAXSilverlight.NET Framework

dotNetManía

Revista dedicada a los profesionales de la plataforma .NET

Menú

Inicio

Números publicados

Libros

Próximo número (nº51)

Autores

¿Qué es dotNetManía?

Garantía de satisfacción

Contactar

Pedidos

Suscripciones

Renovaciones

Libros

Noticias dnm

Alhambra-Eidos llega a un acuerdo con dotNetManía para la difusión conjunta de su oferta formativa. Leer más...


Disponibles los primeros 28 números de dotNetManía en formato PDF y de libre distribución. Leer más... 

Patrocinadores

Patrocinador Oro
Microsoft

Patrocinadores Plata
Alhambra-Eidos
Solid Quality Mentors

Patrocinadores Bronce
Raona
Plain Concepts
Krasis
ABOX 

 

 

 

Nº 3 Abril 2004 Gestión de concurrencia en ADO.NET Material de apoyo

Por Jesús López
 

La concurrencia, en un entorno multiusuario, es siempre una cuestión problemática, pero si además se trata de un entorno desconectado como el que se usa en ADO.NET con sus DataSets y DataAdapters, la problemática es aún mayor debido a la propia naturaleza desconectada del entorno.


Los conflictos de concurrencia no se producen
solamente al actualizar un registro porque otro usuario
lo haya modificado, también ocurren si el registro
ha sido eliminado por otro usuario

Proyecto

SQLAdapter.EXE

 


 

Más información

David Burgett-msdn

Tackle Data Concurrency Exceptions Using the DataSet Object

 

Builder.com

Pessimistic locking solves ADO.NET concurrency problems

How to handle optimistic concurrency violations in ADO.NET

An introduction to ADO.NET concurrency

 


Código fuente

CREATE TABLE Empleados (

       IdEmpleado INT IDENTITY(1,1) PRIMARY KEY,

       DNI VARCHAR(12) NOT NULL UNIQUE,

       Nombre VARCHAR(50) NOT NULL,

       Apellidos VARCHAR(50) NOT NULL

)

 

UPDATE Empleados

SET    DNI=@DNI, Nombre=@Nombre, Apellidos=@Apellidos

WHERE  IdEmpleado=@Original_IdEmpleado AND DNI=@Original_DNI AND

       Nombre=@Original_Nombre AND Apellidos=@Original_Apellidos

 

UPDATE Empleados

SET    DNI=@DNI, Nombre=@Nombre, Apellidos=@Apellidos

WHERE  IdEmpleado=@Original_IdEmpleado

 

UPDATE Empleados

SET    DNI=@DNI, Nombre=@Nombre, Apellidos=@Apellidos

WHERE  IdEmpleado=@Original_IdEmpleado AND DNI=@Original_DNI AND

       Nombre=@Original_Nombre AND Apellidos=@Original_Apellidos

 

UPDATE Empleados

SET    DNI=@DNI, Nombre=@Nombre, Apellidos=@Apellidos

WHERE  IdEmpleado=@Original_IdEmpleado

 

SqlDataAdapter Adapter = new

               SqlDataAdapter("SELECT * FROM Empleados", Connection);

SqlCommandBuilder CommandBuilder = new SqlCommandBuilder(Adapter);

Adapter.UpdateCommand = CommandBuilder.GetUpdateCommand();

Adapter.InsertCommand = CommandBuilder.GetInsertCommand();

Adapter.DeleteCommand = CommandBuilder.GetDeleteCommand();

 

public void Guardar(DataTable Empleados)

{

  // creamos un adapter para realizar la actualización

  SqlDataAdapter Adapter = new SqlDataAdapter("SELECT * FROM Empleados", this.cn);

 

  // usamos un command builder para configurar los comandos de actualización

  SqlCommandBuilder CommandBuilder = new SqlCommandBuilder(Adapter);

  Adapter.UpdateCommand = CommandBuilder.GetUpdateCommand();

  Adapter.InsertCommand = CommandBuilder.GetInsertCommand();

  Adapter.DeleteCommand = CommandBuilder.GetDeleteCommand();

 

  // este comando nos sirve para refrescar un registro

  SqlCommand Resync = new SqlCommand("SELECT * From Empleados

                                      WHERE IdEmpleado=@IdEmpleado", this.cn);

  Resync.Parameters.Add("@IdEmpleado", SqlDbType.Int);

 

  try

  {

    Adapter.Update(Empleados);

  }

  catch ( DBConcurrencyException ex )

  {

    // Nuestra respuesta a un conflicto va a ser refrescar el registro

    Adapter.SelectCommand = Resync;

    Resync.Parameters["@IdEmpleado"].Value=ex.Row["IdEmpleado",

                      DataRowVersion.Original];

 

    // el método Fill buscará el registro en el DataTable

    // por clave primaria (IdEmpleado) y lo "refrescará"

    if ( Adapter.Fill(Empleados) == 0 )

    // la causa del conflicto es que ha sido eliminado

    // (Fill devuelve cero registros)

    {

      if ( ex.Row.RowState == DataRowState.Deleted )

      {

        // en este punto tenemos un conflicto de concurrencia

        // al eliminar un registro porque ha sido eliminado.

 

        // Eliminamos definitivamente el registro

        ex.Row.AcceptChanges();

        // ignoramos el conflicto y seguimos con la actualización

        Guardar(Empleados);

       }

       else

       {p;   {

         // en este punto tenemos un conflicto de concurrencia

         // al modificar un registro porque ha sido eliminado

 

         // Eliminamos el registro

         // y volvemos a lanzar la excepción

         ex.Row.Delete();

         ex.Row.AcceptChanges();

         throw ex;

       }

     }

     else

     {

        // la causa del conflicto es que ha sido modificado

 

        // Si el conflicto ha sido al eliminar el registro

        // Fill ya lo habrá "recuperado" y refrescado.

        // Aparecerá el registro con el error

 

        // Si el conflicto ha sido al modificar el registro

        // Fill lo habrá "refrescado". Y aparecerá el registro

        // con el error

 

        // sólo hay que volver a lanzar la excepción

        throw ex;

      }

    }

}

Fuente 1. Ejemplo de gestión de conflictos de concurrencia

Volver
 

 

dotNetManía es una revista editada por Netalia. Más información.