Concurrencia Optimista y Concurrencia Pesimista
Para este artículo es necesario comprender estos dos conceptos que son muy sencillos aunque
el nombre haga pensar que es algo complejo. En entornos multiusuario donde se accede a una
base de datos, por ejemplo un sitio web. es común que dos o más personas estén
editando algún campo de la base de datos al mismo tiempo.
Vamos a suponer que tenemos un sitio web y varios administradores editando campos de la
base de datos y en ese momento dos de ellos están editando el mismo campo. El
“Administrador A y el B”. Los dos comienzan a editar el campo al mismo tiempo, el
“Administrador A” comienza a editar y luego se va a tomar un café, mientras que el
“Administrador B“ edita y guarda rápidamente el campo modificado.
Al regresar el “Administrador A” no va a tener la información actualizada de la base de
datos por lo que podrían producirse problemas futuros. En teoría hay dos formas de tratar
con un escenario de este estilo aquí es donde aparecen los dos conceptos de concurrencia
optimista y pesimista
En el caso de la concurrencia pesimista, nos dice que debemos permitir editar cualquier
campo de la base de datos sólo a un usuario a la vez y bloquear el acceso al campo a
cualquier otro usuario que intente editar el campo.
Desde mi punto de vista este tipo de concurrencia es problemática, tomando el ejemplo
anterior, cualquier otro administrador debe esperar a que el “Administrador A” termine el
café para poder editar el campo de la base de datos.
La concurrencia optimista, por otro lado es más permisiva ya que permite que cualquier
usuario edite el campo de la base de datos y en caso de que se produzca alguna modificación
mientras todavía editando se le informará al usuario de que se han producido cambios en la
base de datos.
Si tomamos el ejemplo anterior, cuando el “Administrador A” regrese de tomarse el café e
intente guardar el campo modificado el sistema le informará que el campo ha sido modificado
y volverá a cargar la información actualizada de la base de datos o cualquier otra acción
que se requiera.
Ejemplo
Para entender el ejemplo es necesario tener conocimientos básicos de Entity Framework y de
Code First. Este link Get Started
with Entity Framework (EF) tiene toda la información necesaria para comenzar.
Vamos a utilizar un modelo de dominio muy sencillo basado en una sola entidad “Game” juego
que tiene dos propiedades el ID y el Nombre. Este ejemplo es también es válido para
entidades más complejas.
Nota: El ejemplo está programado en Visual Studio 2012 utilizando Entity Framework 5 Code
First. Puedes descargarlo desde el siguiente enlace: Ejemplo de EntityFramework y
Concurrencia Optimista
Primero definimos la entidad Game
public class Game { public int GameId { get; set; } public string Name { get; set; } //Este campo va a ser usado por EF para chequear la concurrencia public byte[] RowVersion { get; set; } }
Luego creamos la clase GameDbContext que nos va a permitir vincular nuestra base de datos
con EF.
public class GameDbContext : DbContext { public DbSetGames { get; set; } }
El paso siguiente es informar a EF que la columna RowVersion sea utilizada para verificar
que la fila no haya sido modificada. Esto lo podemos hacer de dos maneras con Anotaciones o
utilizando “Fluent Api”.
Con anotaciones
Basta con decorar con la anotación Timestamp la propiedad RowVersion
[Timestamp] public byte[] RowVersion { get; set; }
Con Fluent Api
Si no queremos “ensuciar” el modelo de dominio con anotaciones podemos utilizar “Fluent
Api” Para ello debemos sobrescribir el método OnModelCreating de la clase GameDbContext y
utilizar el método IsRowVersion() en la propiedad RowVersion.
public class GameDbContext : DbContext { public DbSetGames { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity ().Property(g => g.RowVersion).IsRowVersion(); } }
Ahora si cualquier campo de la fila ha sido modificado mientras otro usuario este editando EF generara la excepción “DbUpdateConcurrencyException”
try { context.SaveChanges(); } catch (DbUpdateConcurrencyException e) { //Manejar la excepcion Game newGame = ((Game)e.Entries.First().Entity); Console.WriteLine("La entidad ha sido modificada el nuevo nombre es: {0}", newGame.Name); }
Cabe destacar que esta clase regresa en la propiedad e.Entries las entidades que fueron
modificadas y el valor actual de la entidad.
El ejemplo del artículo
es una aplicación de consola, hay que ejecutarla dos veces y luego
pulsar cualquier tecla en una de las ventanas y después cualquier tecla en la otra. La
última instancia va a intentar modificar el campo Game mientras que en la otra ventana ya
se había modificado por lo que se producirá una excepción.
"Administrador A" Informamos que la entidad ha sido modificada
Saludos!.
Referencias
Utilizar concurrencia optimista
Get Started with Entity Framework (EF)
No hay comentarios:
Publicar un comentario