Bloquear registro en sql server

26/01/2006 - 04:25 por Juan Melas | Informe spam
Me piden en un sistema en capas bloquear un registro para que no pueda ser
accedido por otro usuario mientras esta siendo editado, hay alguna forma de
hacerlo?

Preguntas similare

Leer las respuestas

#1 Jesús López
26/01/2006 - 09:00 | Informe spam
Eso suele ser una muy mala práctica, así que tienes que tener muy buenas
razones para hacerlo. ¿Podrías explicarnos las razones por las que es
necesario hacer esto?. Por otra parte no das información acerca de tu
sistema de capas. ¿Podrías darnos más detalles?:

(1) Sistema de base de datos que estás usando, versión y edición
(2) Tipo de sistema de capas:
- Son sólo capas lógicas usando una arquitectura cliente windows -
servidor de base de datos
- Son capas físicas:
- Servidor de base de datos
- Servidor de aplicaciones (Servicios Web, .NET Remoting, Enterprise
Services)
- Tipo de aplicación cliente (aplicación web o aplicación Windows)

Saludos:

Jesús López
MVP
Respuesta Responder a este mensaje
#2 Juan Melas
27/01/2006 - 02:08 | Informe spam
Es para un estudio jurídico en que trabajan desde varias
terminales me piden que cuando un caso lo está editando un abogado nadie más
lo pueda editar, actualmente tienen un sistema con dbf de fox en el que
existe la función lock() que permite bloquear un registro, la quiero pasar a
sql server(en realidad msde) por razones de seguridad , paso los detalles

1-La base de datos es msde.
2-Es una aplicación de capas lógicas cliente windows .

Gracias



"Jesús López" escribió en el mensaje
news:
Eso suele ser una muy mala práctica, así que tienes que tener muy buenas
razones para hacerlo. ¿Podrías explicarnos las razones por las que es
necesario hacer esto?. Por otra parte no das información acerca de tu
sistema de capas. ¿Podrías darnos más detalles?:

(1) Sistema de base de datos que estás usando, versión y edición
(2) Tipo de sistema de capas:
- Son sólo capas lógicas usando una arquitectura cliente windows -
servidor de base de datos
- Son capas físicas:
- Servidor de base de datos
- Servidor de aplicaciones (Servicios Web, .NET Remoting,
Enterprise Services)
- Tipo de aplicación cliente (aplicación web o aplicación Windows)

Saludos:

Jesús López
MVP

Respuesta Responder a este mensaje
#3 Jesús López
27/01/2006 - 12:02 | Informe spam
Bueno, me imagino que si están acostumbrados a trabajar con bloqueos
pesimistas les costará cambiar a bloqueo optimista, donde el usuario se
entera de que otro usuario ha modificado el registro después de intentar
guardarlo, esto no suele ser un problema a no ser que ocurra demasiado a
menudo y yo dudo mucho que en un estudio jurídico eso pudiera ocurrir más de
una vez al año.

La regla de negocio se está cumpliendo con el bloqueo optimista, ya que si
dos usuarios se ponen a editar el mismo registro al mismo tiempo, sólo uno de
los dos tiene éxito, este es el primero que llega, el segundo recibe un error
de concurrencia al intentar guardar. Con el bloqueo pesimista ocurre lo
mismo, el primero que llega es el que gana, la diferencia es que en el
bloqueo pesimista el usuario se entera antes de empezar a editar, mientras
que en el optimista se entera después.

Deberías hacerles a los usuarios la siguiente pregunta:

¿ Cuantas veces en un año, has tenido que editar un caso y estaba bloqueado ?

Si la respuesta es "muchas veces" entonces el bloqueo optimista puede que no
sea adecuado, ya que prodría producir frustración en los usuarios si reciben
muchas veces el error de concurrencia y tienen que volver a empezar a hacer
los cambios. Aunque también es verdad que de esas muchas veces puede que en
bastantes ocasiones en realidad el usuario que tenía bloqueado el caso estaba
tomándose un café o estaba hablando por teléfono o haciendo cualquier otra
cosa menos editar el caso, impidiendo trabajar a los demás en el caso sin
ninguna razón.

Si la respuesta es "pues no recuerdo ninguna" entonces el bloqueo optimista
es adecuado sin lugar a dudas.

También habría que preguntarles ¿Cuantas veces has tenido a editar un caso,
estaba bloqueado, y quien lo tenía bloqueado estaba haciendo cualquier otra
cosa menos editarlo (lo tenía en la pantalla, pero no le hacía caso), has ido
a su despacho, y le has dicho, pero hombre desbloquea de una vez ese caso,
que lo tengo que editar?

Si la respuesta es "bastance a menudo" entonces el bloqueo pesimista está
causando más problemas de los que soluciona y sería preferible un bloqueo
optimista.

Generalmente las aplicaciones antiguas funcionan con bloqueos pesimistas
mientras que las modernas con optimistas. Cuando un desarrollador tiene que
migrar una aplicación antigua se encuentra con el problema de que los
usuarios quieren mantener el bloqueo pesimista y es difícil convencerles para
usar uno optimista.

Sin embargo, a veces un bloqueo pesismista es lo adecuado, así que te voy a
contar dos técnicas para implementarlo:
(1) Basado en bloqueos de servidor (el bloqueo pesimista de toda la vida)
(2) La técnica "Check in - Check out"

La primera requiere manetener una conexión abierta y una transacción en
curso, por tanto es una solución no escalable, rompe con el modo desconectado
tan familiar en ADO.NET y no permite saber quien es el usuario que tiene
bloqueado el registro.

La segunda se basa en lógica de actualización, es escalable, permite
mantener el modo desconectado y permite saber quien es el usuario que tienen
bloqueado el registro.

Bloqueos de servidor

Para bloquear un registro comenzamos una transacción con
Connection.BeginTransaction() y ejecutamos lo siguiente mediante un
SqlCommand y el método ExecuteScalar:

SET LOCK_TIMEOUT 100
SELECT IdCaso FROM Casos WITH(UPDLOCK) WHERE IdCaso = @IdCaso

Si ExecuteScalar nos devuelve el IdCaso, es que hemos bloqueado el registro.
Si el registro estaba bloqueado ya por otro usuario entonces recibiremos una
excepción SqlException:

Número de error: 1222
Mensaje: "Lock request time out period exceeded"

La conexión hay que mantenerla abierta.

El bloqueo se mantendrá hasta que se termine la transación bien con
Transaction.Commit() o con Transaction.Rollback()

El bloqueo es un bloqueo de actualización, que impide que otra conexión
(aunque sea del mismo usuario en la misma máquina en la misma instancia de la
aplicación) modifique o elimine el registro u obtenga un bloqueo de
actualización. Sin embargo permite que cualquier conexión lea el registro. O
sea que aunque el registro esté bloqueado de esta manera, no impide que otra
conexión lea el registro, por lo que puedes usar un DataAdapter con otra
conexión y una select como SELECT * FROM Casos para cargar los registros en
un DataTable.

Pero para guardar los registros en la base de datos tienes que usar la misma
conexión con la que bloqueaste el registro. Una vez actualizados los datos,
el bloqueo de actualización se convierte en bloqueo exclusivo que impide que
cualquier otra conexión acceda de cualquier forma al registro. Por esta razón
y para que los cambios tengan efecto permanente será conveniente llamar a
Transaction.Commit(). A partir de este momento los cambios han tenido efecto
y los bloqueos han sido liberados.

Check in - check out

Esta técnica consite en hacer un "check in" antes de editar un registro para
bloquearlo y hacer un "check out" para desbloquearlo. La lógica de
actualización debe comprobar que ya se ha hecho el correpondiente "check in".

En la tabla de Casos añadimos el campo CheckedBy que indica el usuario que
está editando el registro o un valor nulo si el registro está libre.


CREATE TABLE Casos
(
IdCaso INT IDENTITY(1,1) PRIMARY KEY,
DatosCaso VARCHAR(100),
CheckedBy VARCHAR(100)
)
GO

NOTA: por simplicidad del ejemplo sólo he puesto un campo de información en
la tabla (DatosCaso)

Suponiendo que la aplicación usa autentificación Windows para conectarse a
SQL Server y que cada usario tiene su propia cuenta de seguridad de Windows.
Estos serían los procedimientos almacenados para hacer check in y check out:

El procedimiento CheckInCaso, se le pasa como parámetro de entrada el Id del
caso que se quiere bloquear, @CheckedBy es un parámetro de salida que nos
dice el usuario que tiene bloqueado el registro en caso de que ya alguien lo
tuviera bloqueado. El procedimiento devuelve:

0: si el check in ha tenido éxito o estaba bloqueado por el mismo usuario
-1: si ya estaba bloqueado por otro usuario
-2: si el caso no existe

CREATE PROCEDURE CheckInCaso
@IdCaso INT,
@CheckedBy VARCHAR(100) OUTPUT
AS
UPDATE Casos
SET CheckedBy = SUSER_SNAME()
WHERE IdCaso = @IdCaso AND (CheckedBy IS NULL OR CheckedBy = SUSER_SNAME())
IF @@ROWCOUNT = 0
BEGIN
SELECT @CheckedBy = CheckedBy
FROM Casos
WHERE IdCaso = @IdCaso
IF @@ROWCOUNT = 0
BEGIN
SET @CheckedBy = NULL
RETURN -2 -- El caso no existe
END
ELSE
BEGIN
RETURN -1 -- El caso está bloqueado por otro usuario @User
END
END
ELSE
BEGIN
RETURN 0 -- El caso ha sido bloqueado con éxito o ya estaba bloqueado por
el mismo usuario
END


El procedimiento CheckOutCaso es similar, IdCaso es el id del caso que se
quiere desbloquear y @ChackedBy un parámetro de salida que informa del
usuario que tiene bloqueado el registro en caso de que sea uno diferente del
que quiere desbloquearlo.

Devuelve:
-1: si el caso está bloqueado por otro usuario
-2: si el caso no existe
0: si el caso ha sido desbloqueado con éxito o ya estaba desbloqueado.

CREATE PROCEDURE CheckOutCaso
@IdCaso INT,
@CheckedBy VARCHAR(100) OUTPUT
AS
UPDATE Casos
SET CheckedBy = NULL
WHERE IdCaso = @IdCaso AND (CheckedBy = SUSER_SNAME() OR CheckedBy IS NULL)
IF @@ROWCOUNT = 0
BEGIN
SELECT @CheckedBy = CheckedBy
FROM Casos
WHERE IdCaso = @IdCaso
IF @@ROWCOUNT = 0
BEGIN
SET @CheckedBy = NULL
RETURN -2 -- El caso no existe
END
ELSE
BEGIN
RETURN -1 -- El caso está bloqueado por otro usuario @CheckedBy
END
END
ELSE
BEGIN
RETURN 0 -- El caso ha sido desbloqueado con éxito o ya estaba desbloqueado
END
GO

También sería conveniente tener un procedimiento almacenado que desbloqueara
todos:

CREATE PROCEDURE ChecOutAllCaso
AS
UPDATE Casos SET CheckedBy = NULL WHERE CheckedBy = SUSER_SNAME()


Para modificar un caso crearíamos el siguiente procedimiento almacenado que
comprueba que el usuario actual es quien tiene bloqueado el registro:

CREATE PROCEDURE ModificarCaso
@IdCaso int,
@DatosCaso VARCHAR(100),
AS
UPDATE Casos
SET DatosCaso = @DatosCaso
WHERE IdCaso = @IdCaso AND CheckedBy = SUSER_SNAME()

Desde la aplicación cliente debemos usar este procedimiento almacenado para
modificar los casos y comprobar el número de registros afectados. Si el
número de registros afectados es cero, es que o bien el registro se ha
eliminado o está bloqueado por otro usuario. Si la actualización la hacemos
por medio de un DataAdapter, su UpdateCommand deberá ser este procedimiento
almacenado. La buena noticia es que el propio DataAdapter comprobará el
número de registros afectados y lanzará una excepción DbConcurrencyViolation
si el número de registros afectados por el UpdateCommand es cero, (así es
como funcionan siempre los DataAdapter)

Saludos:

Jesús López
MVP VB
Solid Quality Learning
www.solidqualitylearning.com



"Juan Melas" escribió:


Es para un estudio jurídico en que trabajan desde varias
terminales me piden que cuando un caso lo está editando un abogado nadie más
lo pueda editar, actualmente tienen un sistema con dbf de fox en el que
existe la función lock() que permite bloquear un registro, la quiero pasar a
sql server(en realidad msde) por razones de seguridad , paso los detalles

1-La base de datos es msde.
2-Es una aplicación de capas lógicas cliente windows .

Gracias



"Jesús López" escribió en el mensaje
news:
> Eso suele ser una muy mala práctica, así que tienes que tener muy buenas
> razones para hacerlo. ¿Podrías explicarnos las razones por las que es
> necesario hacer esto?. Por otra parte no das información acerca de tu
> sistema de capas. ¿Podrías darnos más detalles?:
>
> (1) Sistema de base de datos que estás usando, versión y edición
> (2) Tipo de sistema de capas:
> - Son sólo capas lógicas usando una arquitectura cliente windows -
> servidor de base de datos
> - Son capas físicas:
> - Servidor de base de datos
> - Servidor de aplicaciones (Servicios Web, .NET Remoting,
> Enterprise Services)
> - Tipo de aplicación cliente (aplicación web o aplicación Windows)
>
> Saludos:
>
> Jesús López
> MVP
>



Respuesta Responder a este mensaje
#4 Juan Melas
28/01/2006 - 03:54 | Informe spam
Muchas gracias Jesús muy clara tu explicación, estaba pensando en la segunda
opción la de "check in check out" estoy estudiando la forma de desbloquear
si un usuario sale mal del sistema o sufre un cuelge y deja el registro con
la marca de bloqueado haciéndolo inaccesible.


"Jesús López" escribió en el mensaje
news:
Bueno, me imagino que si están acostumbrados a trabajar con bloqueos
pesimistas les costará cambiar a bloqueo optimista, donde el usuario se
entera de que otro usuario ha modificado el registro después de intentar
guardarlo, esto no suele ser un problema a no ser que ocurra demasiado a
menudo y yo dudo mucho que en un estudio jurídico eso pudiera ocurrir más
de
una vez al año.

La regla de negocio se está cumpliendo con el bloqueo optimista, ya que si
dos usuarios se ponen a editar el mismo registro al mismo tiempo, sólo uno
de
los dos tiene éxito, este es el primero que llega, el segundo recibe un
error
de concurrencia al intentar guardar. Con el bloqueo pesimista ocurre lo
mismo, el primero que llega es el que gana, la diferencia es que en el
bloqueo pesimista el usuario se entera antes de empezar a editar, mientras
que en el optimista se entera después.

Deberías hacerles a los usuarios la siguiente pregunta:

¿ Cuantas veces en un año, has tenido que editar un caso y estaba
bloqueado ?

Si la respuesta es "muchas veces" entonces el bloqueo optimista puede que
no
sea adecuado, ya que prodría producir frustración en los usuarios si
reciben
muchas veces el error de concurrencia y tienen que volver a empezar a
hacer
los cambios. Aunque también es verdad que de esas muchas veces puede que
en
bastantes ocasiones en realidad el usuario que tenía bloqueado el caso
estaba
tomándose un café o estaba hablando por teléfono o haciendo cualquier otra
cosa menos editar el caso, impidiendo trabajar a los demás en el caso sin
ninguna razón.

Si la respuesta es "pues no recuerdo ninguna" entonces el bloqueo
optimista
es adecuado sin lugar a dudas.

También habría que preguntarles ¿Cuantas veces has tenido a editar un
caso,
estaba bloqueado, y quien lo tenía bloqueado estaba haciendo cualquier
otra
cosa menos editarlo (lo tenía en la pantalla, pero no le hacía caso), has
ido
a su despacho, y le has dicho, pero hombre desbloquea de una vez ese caso,
que lo tengo que editar?

Si la respuesta es "bastance a menudo" entonces el bloqueo pesimista está
causando más problemas de los que soluciona y sería preferible un bloqueo
optimista.

Generalmente las aplicaciones antiguas funcionan con bloqueos pesimistas
mientras que las modernas con optimistas. Cuando un desarrollador tiene
que
migrar una aplicación antigua se encuentra con el problema de que los
usuarios quieren mantener el bloqueo pesimista y es difícil convencerles
para
usar uno optimista.

Sin embargo, a veces un bloqueo pesismista es lo adecuado, así que te voy
a
contar dos técnicas para implementarlo:
(1) Basado en bloqueos de servidor (el bloqueo pesimista de toda la vida)
(2) La técnica "Check in - Check out"

La primera requiere manetener una conexión abierta y una transacción en
curso, por tanto es una solución no escalable, rompe con el modo
desconectado
tan familiar en ADO.NET y no permite saber quien es el usuario que tiene
bloqueado el registro.

La segunda se basa en lógica de actualización, es escalable, permite
mantener el modo desconectado y permite saber quien es el usuario que
tienen
bloqueado el registro.

Bloqueos de servidor

Para bloquear un registro comenzamos una transacción con
Connection.BeginTransaction() y ejecutamos lo siguiente mediante un
SqlCommand y el método ExecuteScalar:

SET LOCK_TIMEOUT 100
SELECT IdCaso FROM Casos WITH(UPDLOCK) WHERE IdCaso = @IdCaso

Si ExecuteScalar nos devuelve el IdCaso, es que hemos bloqueado el
registro.
Si el registro estaba bloqueado ya por otro usuario entonces recibiremos
una
excepción SqlException:

Número de error: 1222
Mensaje: "Lock request time out period exceeded"

La conexión hay que mantenerla abierta.

El bloqueo se mantendrá hasta que se termine la transación bien con
Transaction.Commit() o con Transaction.Rollback()

El bloqueo es un bloqueo de actualización, que impide que otra conexión
(aunque sea del mismo usuario en la misma máquina en la misma instancia de
la
aplicación) modifique o elimine el registro u obtenga un bloqueo de
actualización. Sin embargo permite que cualquier conexión lea el registro.
O
sea que aunque el registro esté bloqueado de esta manera, no impide que
otra
conexión lea el registro, por lo que puedes usar un DataAdapter con otra
conexión y una select como SELECT * FROM Casos para cargar los registros
en
un DataTable.

Pero para guardar los registros en la base de datos tienes que usar la
misma
conexión con la que bloqueaste el registro. Una vez actualizados los
datos,
el bloqueo de actualización se convierte en bloqueo exclusivo que impide
que
cualquier otra conexión acceda de cualquier forma al registro. Por esta
razón
y para que los cambios tengan efecto permanente será conveniente llamar a
Transaction.Commit(). A partir de este momento los cambios han tenido
efecto
y los bloqueos han sido liberados.

Check in - check out

Esta técnica consite en hacer un "check in" antes de editar un registro
para
bloquearlo y hacer un "check out" para desbloquearlo. La lógica de
actualización debe comprobar que ya se ha hecho el correpondiente "check
in".

En la tabla de Casos añadimos el campo CheckedBy que indica el usuario que
está editando el registro o un valor nulo si el registro está libre.


CREATE TABLE Casos
(
IdCaso INT IDENTITY(1,1) PRIMARY KEY,
DatosCaso VARCHAR(100),
CheckedBy VARCHAR(100)
)
GO

NOTA: por simplicidad del ejemplo sólo he puesto un campo de información
en
la tabla (DatosCaso)

Suponiendo que la aplicación usa autentificación Windows para conectarse a
SQL Server y que cada usario tiene su propia cuenta de seguridad de
Windows.
Estos serían los procedimientos almacenados para hacer check in y check
out:

El procedimiento CheckInCaso, se le pasa como parámetro de entrada el Id
del
caso que se quiere bloquear, @CheckedBy es un parámetro de salida que nos
dice el usuario que tiene bloqueado el registro en caso de que ya alguien
lo
tuviera bloqueado. El procedimiento devuelve:

0: si el check in ha tenido éxito o estaba bloqueado por el mismo usuario
-1: si ya estaba bloqueado por otro usuario
-2: si el caso no existe

CREATE PROCEDURE CheckInCaso
@IdCaso INT,
@CheckedBy VARCHAR(100) OUTPUT
AS
UPDATE Casos
SET CheckedBy = SUSER_SNAME()
WHERE IdCaso = @IdCaso AND (CheckedBy IS NULL OR CheckedBy =
SUSER_SNAME())
IF @@ROWCOUNT = 0
BEGIN
SELECT @CheckedBy = CheckedBy
FROM Casos
WHERE IdCaso = @IdCaso
IF @@ROWCOUNT = 0
BEGIN
SET @CheckedBy = NULL
RETURN -2 -- El caso no existe
END
ELSE
BEGIN
RETURN -1 -- El caso está bloqueado por otro usuario @User
END
END
ELSE
BEGIN
RETURN 0 -- El caso ha sido bloqueado con éxito o ya estaba bloqueado por
el mismo usuario
END


El procedimiento CheckOutCaso es similar, IdCaso es el id del caso que se
quiere desbloquear y @ChackedBy un parámetro de salida que informa del
usuario que tiene bloqueado el registro en caso de que sea uno diferente
del
que quiere desbloquearlo.

Devuelve:
-1: si el caso está bloqueado por otro usuario
-2: si el caso no existe
0: si el caso ha sido desbloqueado con éxito o ya estaba desbloqueado.

CREATE PROCEDURE CheckOutCaso
@IdCaso INT,
@CheckedBy VARCHAR(100) OUTPUT
AS
UPDATE Casos
SET CheckedBy = NULL
WHERE IdCaso = @IdCaso AND (CheckedBy = SUSER_SNAME() OR CheckedBy IS
NULL)
IF @@ROWCOUNT = 0
BEGIN
SELECT @CheckedBy = CheckedBy
FROM Casos
WHERE IdCaso = @IdCaso
IF @@ROWCOUNT = 0
BEGIN
SET @CheckedBy = NULL
RETURN -2 -- El caso no existe
END
ELSE
BEGIN
RETURN -1 -- El caso está bloqueado por otro usuario @CheckedBy
END
END
ELSE
BEGIN
RETURN 0 -- El caso ha sido desbloqueado con éxito o ya estaba
desbloqueado
END
GO

También sería conveniente tener un procedimiento almacenado que
desbloqueara
todos:

CREATE PROCEDURE ChecOutAllCaso
AS
UPDATE Casos SET CheckedBy = NULL WHERE CheckedBy = SUSER_SNAME()


Para modificar un caso crearíamos el siguiente procedimiento almacenado
que
comprueba que el usuario actual es quien tiene bloqueado el registro:

CREATE PROCEDURE ModificarCaso
@IdCaso int,
@DatosCaso VARCHAR(100),
AS
UPDATE Casos
SET DatosCaso = @DatosCaso
WHERE IdCaso = @IdCaso AND CheckedBy = SUSER_SNAME()

Desde la aplicación cliente debemos usar este procedimiento almacenado
para
modificar los casos y comprobar el número de registros afectados. Si el
número de registros afectados es cero, es que o bien el registro se ha
eliminado o está bloqueado por otro usuario. Si la actualización la
hacemos
por medio de un DataAdapter, su UpdateCommand deberá ser este
procedimiento
almacenado. La buena noticia es que el propio DataAdapter comprobará el
número de registros afectados y lanzará una excepción
DbConcurrencyViolation
si el número de registros afectados por el UpdateCommand es cero, (así es
como funcionan siempre los DataAdapter)

Saludos:

Jesús López
MVP VB
Solid Quality Learning
www.solidqualitylearning.com



"Juan Melas" escribió:


Es para un estudio jurídico en que trabajan desde
varias
terminales me piden que cuando un caso lo está editando un abogado nadie
más
lo pueda editar, actualmente tienen un sistema con dbf de fox en el que
existe la función lock() que permite bloquear un registro, la quiero
pasar a
sql server(en realidad msde) por razones de seguridad , paso los
detalles

1-La base de datos es msde.
2-Es una aplicación de capas lógicas cliente windows .

Gracias



"Jesús López" escribió en el mensaje
news:
> Eso suele ser una muy mala práctica, así que tienes que tener muy
> buenas
> razones para hacerlo. ¿Podrías explicarnos las razones por las que es
> necesario hacer esto?. Por otra parte no das información acerca de tu
> sistema de capas. ¿Podrías darnos más detalles?:
>
> (1) Sistema de base de datos que estás usando, versión y edición
> (2) Tipo de sistema de capas:
> - Son sólo capas lógicas usando una arquitectura cliente windows -
> servidor de base de datos
> - Son capas físicas:
> - Servidor de base de datos
> - Servidor de aplicaciones (Servicios Web, .NET Remoting,
> Enterprise Services)
> - Tipo de aplicación cliente (aplicación web o aplicación Windows)
>
> Saludos:
>
> Jesús López
> MVP
>



Respuesta Responder a este mensaje
#5 Jesús López
28/01/2006 - 10:18 | Informe spam
Efectivamente eso es posible que ocurra y no cabe duda de que alguna vez
ocurrirá, así que habrá que tener una estrategia para tratarlo.

NOTA: el registro no está inaccesible, sólo aparece como no editable para
todos los demás usuarios. La aplicación no impide leerlo.

Se me ocurren varias estrategias:

(1) La aplicación elimina todos los bloqueos del usuario en cuestión cada
vez que arranca y finaliza. Esto no impide el problema, pero reduce su
ocurrencia.
(2) Incluir un campo de fecha, con la fecha y hora del bloqueo.
(3) Ejecutar periódicamente un procedimiento almacenado que elimine todos
los bloqueos con una determinada antigüedad. Con esto limitamos el tiempo
que un registro puede estar bloqueado.
(4) La aplicación podría darle al usuario la posibilidad de "renovar" el
bloqueo cuando falte poco tiempo para que caduque.
(5) Una vez que el bloqueo lleva activo más una determinada cantidad de
tiempo, los demás usuarios pueden forzar su desbloqueo.
(6) Monitorizar los usuarios que tienen abierta la aplicación y eliminar
todos los bloqueos de aquellos que no estén activos. Las aplicaciones
cliente podrían enviar un mensaje de "El usuario tal está activo" cada pocos
minutos a una aplicación en el servidor. La aplicación en el servidor
eliminará todos los bloqueos de todos los usuarios de los que no se haya
recibido un mensaje de actividad durante los últimos x minutos. Esto podría
implementarse de la siguiente manera:
(a) La aplicación de servidor podría ser un servicio windows que
estubiera escuchando en un puerto UDP. Las aplicaciones cliente mandan el
mensaje por UDP al servidor
(b) La aplicación de servidor podría ser un servicio windows que
expusiera un objeto SingleCall de .NET Remoting. Las aplicaciones cliente
invocarían un método de este objeto remoto
(c) La aplicación de servidor podría ser un servicio web. Las
aplicaciones cliente, invocarían un método de este servicio web.

Saludos:

Jesús López
MVP
Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente Respuesta Tengo una respuesta
Search Busqueda sugerida