Acceso exclusivo a la Tabla de la Base de Datos mediante código VBA

13/09/2004 - 03:33 por nadura | Informe spam
Con el siguiente Código mediante ADO puedo conseguir
bloquear un determinado registro de la base de Datos
cuando dos usuarios pretenden acceder a él de forma
simultánea:

Private Sub Command0_Click()
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim strText As String
Dim strConn As String
Dim iCliente As Integer
Dim iClienteValorCambiado As String

On Error GoTo err_ADO:

iCliente = InputBox("Introduzca el Código de Cliente a
buscar:" & vbNewLine & "Debe Introducir un valor
numerico.")
If Len(iCliente) = 0 Then
Exit Sub
End If

iClienteValorCambiado = InputBox("Introduzca el Valor
nuevo:")
If Len(iClienteValorCambiado) = 0 Then
Exit Sub
End If

strConn = "Provider=SQLOLEDB.1;Integrated
Security=SSPI;Persist Security Info=False;Initial
Catalog=Base de Datos SQL Server 2000;Data
Source=WINDOWSXP"
Set cn = New ADODB.Connection
Set rs = New ADODB.Recordset

cn.Open strConn
rs.Open "Select * from [Tabla de Clientes] WHERE
[C_CLIENTE]= " & iCliente, cn, adOpenStatic,
adLockPessimistic < Bloqueo del Registro con número
de cliente coincidente con el criterio de búsqueda.

MsgBox "Registro bloqueado: " & iCliente

Do Until rs.EOF
rs.Fields("N_CLIENTE").Value =
iClienteValorCambiado
MsgBox "Valor cambiado de " & iClienteValor & "
a " & iClienteValorCambiado
rs.MoveNext
Loop

rs.Close
cn.Close

Exit Sub

err_ADO:

MsgBox "Error: " & Err.Description
Resume Next

End Sub


Cuestión a Plantear: ¿Como debería modificar dicho código
para bloquear toda la Tabla, es decir, permitir a un
usuario concreto abrir la Tabla en modo exclusivo,
impidiendo a otros usuarios acceder a ésta, mientras el
primero esté realizando consultas ó modificaciones en la
misma?

¿Existe algún conversor para pasar código en DAO a ADO?

Preguntas similare

Leer las respuestas

#6 Miguel Egea
14/09/2004 - 19:20 | Informe spam
Es cierto Rodrigo, la documetación no dice nada de eso , de hecho el bloqueo
se produce, pero con una transacción implicita, de tla forma que al terminar
la instrucción se libera inmediatamente.
Mi comentario viene por que parece que nuestro amigo, lo que quiere hacer es
algoaasí como bloquear la tabla de clientes completa mientras se hace una
operación más compleja. De ahí mis comentarios.

En resumen, lo que dices es correcot (de hcho tablock bloquea solamente el
statement aún cuando tengas una transacción abierta, hay que combinarlo con
hodllock para que mantenga el bloqueo), de todas formas este bloqueo podría
(sería casi seguro) compartido por lo que otras conexiones podrían leer la
tabla sin ningún problema (no podrían actualizar la tabla). Es decir sería
algo parecido a establecer el nivel de aislamiento en repeatable reads o
serializable.

Saludos
Miguel Egea

En resumen, no te digo que lo que comentabas estubiese mal
"Rodrigo Corral [MVP]" escribió en el mensaje
news:
La documentación no dice nada de que sea necesario tener una


transacción

Totalmente de acuerdo en que bloquear una tabla es algo que afecta
radicalmente a la escalabilidad de una aplicación pero...


Un saludo
Rodrigo Corral González [MVP]

FAQ de microsoft.public.es.vc++
http://rcorral.mvps.org


Respuesta Responder a este mensaje
#7 Miguel Egea
14/09/2004 - 19:29 | Informe spam
Veamos, puedes usar un identity para eso, además si pones la integridad
referencial (clave primaria) nunca tendrías un duplicado, como mucho el
segundo podría obtener un error si calculas el máximo como un Select max,

Además en el caso que planteas lo que quieres es que inserciones bloqueen
inserciones, pero lo que nos pides es que inserciones bloqueen tablas, es
radicalmente distinto, fijate que si lo hacemos así, el jefe de la empresa
no podrá ver su listado de clientes que más compran por que la tabla de
clientes estará bloqueada para dar de alta nuevos clientes, puede suponerte
un problema muy grande.

Tu caso tiene un montón de soluciones distintas, te voy a proponer tres que
funcionan bastante bien, te las pongo en pseudocódigo (las que merece la
pena el pseudocódigo).

1.- Usa un valor identity. (no es buena idea para mostrarselo a los clientes
y puedes tener saltos, pero cumple tu requisito)

2.- create un tabla paralela de claves por ejemplo con la estructura
tabla,id
creaa un procedimiento almacenado con un código parecido a este..


Declare @mierror int
declare @id int
set @mierror=0
if @@trancount=0
begin
set @mierror0 -- no hay transaccion
goto salir
update TAbla set @id=id=id+1 where tabla='tuttalbla'

usalo para el momento de grabar, no muestres ningún código de
antemano, sino que al fina lde la grabación de tu clientes muestras un
mensaje diciendo, se ha grabado correctamente la ficha con código XXXX,.
esta operación dentro de una transacción te serializará las inserciones
nuevas pero no te penalizará en absoluto las conustas a clientes

3.- Usa bloqueos de aplicación, puedes mirar en portalsql.com hay algún
artículo que los explica y pueden servirte para el mismo propósito.



-
Miguel Egea Gómez
Microsoft SQL-Server MVP
Webmaster de PortalSql.Com
¿Te interesa participar en las reuniones
del grupo de Usuarios de SQL-Server y .NET
Se harán en levante de España, (Alicante o Murcia)?




"" escribió en el
mensaje news:188601c499f1$c0038240$
Hola a Todos.
Os agradezco enormemente vuestras sugerencias, y en este
sentido respondiendo a la cuestión de Miguel egea, éste es
el objetivo del bloqueo:

En una Base de Datos SQL server en el Servidor Principal
donde almaceno los datos de los Clientes(Tabla de
Clientes) con un número de registro consecutivo(Siendo
este clave principal); utilizo mediante ADO acceso a la
misma por dos puestos Clientes,Si los usuarios de estos
dos puestos pretenden crear un nuevo registro de Cliente
al mismo tiempo (Planteo el peor de los casos)podrían
ocasionarse problemas de duplicación de registro y por
tanto error en la signación del campo que es clave
principal.

Por ello para evitarlo, si uno de los usuarios logra
acceder a la tabla de forma exclusiva, realiza un bloqueo
de la misma al otro usuario, recuperando el número de
registro a utilizar para el nuevo cliente, desbloqueando
seguidamente dicha Tabla, para que otro usuario pueda
acceder a ella. Por tanto el bloqueo de dicha tabla es
mínimo, evitando así el error antes mencionado.

¿Utilizando el bloqueo optimista obtengo los mismos
resultados?¿Hay algún reporte técnico donde se exprese la
utilización de este tipo de bloqueos?¿Existe book online
sobre ADO en www.microsoft.com/spain?

He intentado expresarme de la forma más clara y sencilla,
espero que sea suficientemente comprensible.

Gracias por vuestra colaboración










La documentación no dice nada de que sea necesario tener


una transacción

Totalmente de acuerdo en que bloquear una tabla es algo


que afecta
radicalmente a la escalabilidad de una aplicación pero...


Un saludo
Rodrigo Corral González [MVP]

FAQ de microsoft.public.es.vc++
http://rcorral.mvps.org


.

Respuesta Responder a este mensaje
#8 Rodrigo Corral [MVP]
15/09/2004 - 09:29 | Informe spam
Es el tipico caso en el que se usa bloqueo de tabla, aunque un bloqueo a
nivel de fila daria el mismo resultado y quiza sea menos costoso. Además
usar el bloqueo a nivel del fila te daria la posibilidad de tener varios
contadores en la tabla.

Tambien podrias hacerlo con una transacción, pero no creo que haya mucha
diferencia en este caso. De todos modos yo siempre prefiero el enfoque de la
transacción, por que es mas portable.

Establecer el nivel de aislamiento (si lo que hace tu programa es lo que
sigue, suficiente con read commited, el valor por defecto)
Begin trans
obtener codigo
generar nuevo codigo
Commit trans

De todas formas seguro que Miguel tiene alguna indicación más que hacernos y
en esto lo que el diga va a misa... ;)


Un saludo
Rodrigo Corral González [MVP]

FAQ de microsoft.public.es.vc++
http://rcorral.mvps.org
Respuesta Responder a este mensaje
#9 Miguel Egea
15/09/2004 - 16:24 | Informe spam
jeje, gracias por tu confianza Rodrigo :-). Lo que dices es correcto pero
obtener código hay que procurar que no sea un select max, porque un select
obtiene bloqueos compartidos, por lo que dos sesiones podrían obtener el
mismo código. En mi otra respuesta pongo las alternativas que veo. Como
además hoy salgo de viaje (lamentablemente no voy a tu tierra), procuraré
escribir un artículo al respecto desde el hotel :-)


-
Miguel Egea Gómez
Microsoft SQL-Server MVP
Webmaster de PortalSql.Com
¿Te interesa participar en las reuniones
del grupo de Usuarios de SQL-Server y .NET
Se harán en levante de España, (Alicante o Murcia)?

"Rodrigo Corral [MVP]" escribió en el mensaje
news:%
Es el tipico caso en el que se usa bloqueo de tabla, aunque un bloqueo a
nivel de fila daria el mismo resultado y quiza sea menos costoso. Además
usar el bloqueo a nivel del fila te daria la posibilidad de tener varios
contadores en la tabla.

Tambien podrias hacerlo con una transacción, pero no creo que haya mucha
diferencia en este caso. De todos modos yo siempre prefiero el enfoque de


la
transacción, por que es mas portable.

Establecer el nivel de aislamiento (si lo que hace tu programa es lo que
sigue, suficiente con read commited, el valor por defecto)
Begin trans
obtener codigo
generar nuevo codigo
Commit trans

De todas formas seguro que Miguel tiene alguna indicación más que hacernos


y
en esto lo que el diga va a misa... ;)


Un saludo
Rodrigo Corral González [MVP]

FAQ de microsoft.public.es.vc++
http://rcorral.mvps.org


Respuesta Responder a este mensaje
#10 Rodrigo Corral [MVP]
15/09/2004 - 21:08 | Informe spam
Interesante lo del articulo. Un patrón para obtener codigos unicos que no
sean identity es algo que seria muy util. Son tipicas las tablas de
secuencias de codigos.

Podrias orientarlo exponiendo las soluciones habituales y erroneas que solo
funcionan con muy baja concurrencia y luego proponer la buena solución. En
cuanto lo tengas mandamelo!!!

Y ya por pedir si lo orientas tanto TSQL como a ADO perfecto!!!

Si necesitas mi colaboración en algo, algun ejemplo de código o lo que sea
me dices...


Un saludo
Rodrigo Corral González [MVP]

FAQ de microsoft.public.es.vc++
http://rcorral.mvps.org
Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida