bloqueo registro

706 views
Skip to first unread message

Sandy

unread,
Feb 7, 2014, 11:36:52 AM2/7/14
to vfpl...@googlegroups.com
Buen dia!!..

Recurro a este grupo para salir de unas dudas y que me den una mano.

Como puedo yo saber en mi aplicacion si otro usuario ya bloqueo la tabla ?
para esto lei que existe flock, en  mi aplicacion yo lo implemento a la hora de agregar un nuevo registro, mas no me esta diciendo si otro usuario ya bloqueo la tabla.. yo  me doy cuenta porque cuando le doy guardar, me guarda ( en apariencia) y si le doy nuevo, me da el codigo anterior, vuelve a guardar y le doy nuevo y me sigue dando el codigo anterior..asi es como e podido identificar que otro usuario esta trabajando la tabla..

Entonces, como puedo hacer:
1. primero saber si la tabla ya esta bloqueada antes que yo agregue un registro nuevo, o modifique?
2. lei que con tener la BD compartida, establecer buffering en 5, y set multilocks on, bastaria par bloquear tablas... todo eso lo tengo en mi bd.

entonces la duda es: si tengo todo lo del punto 2 en mi aplicacion y tambien en el codigo trabajo con flock. ... no estoy haciendo alguna redundancia?


Deseo si poder hacer en mi aplicacion que me indique si otro usuario ya tiene la tabla o cualquier registro, como lo haria?, esto con el fin de que cuando genere el ejecutable que no me de problema.

Orientaciones por favor!!!

Agradecida de ante mano por sus aportes.


Analyzer

unread,
Feb 7, 2014, 11:41:22 AM2/7/14
to vfpl...@googlegroups.com
Ya probaste con ISFLOCKED( ) ?


Saludos!


--
Has recibido este mensaje porque estás suscrito al grupo "Visual Foxpro Latinoamérica" de Grupos de Google.
Visita este grupo en http://groups.google.com/group/vfplatino.

Analyzer

unread,
Feb 7, 2014, 11:58:02 AM2/7/14
to vfpl...@googlegroups.com
>o cualquier registro

De la ayuda de VFP8 en Español:

ISRLOCKED( ) devuelve un valor lógico Verdadero (.T.) si el registro está bloqueado; de lo contrario devuelve un valor lógico Falso (.F.).

ISFLOCKED( ) devuelve un valor lógico verdadero (.T.) si la tabla está bloqueada; de lo contrario, devolverá un valor lógico falso (.F.). ISFLOCKED( ) es similar a SYS(2011), pero devuelve un valor lógico que no necesita localización en el caso de aplicaciones internacionales.

Nota   ISFLOCKED() solamente devuelve Verdadero (.T.) en la estación de trabajo que tiene el archivo bloqueado.

Saludos!


El 7 de febrero de 2014, 10:36, Sandy <sandrab...@gmail.com> escribió:

Sandy

unread,
Feb 7, 2014, 12:12:47 PM2/7/14
to vfpl...@googlegroups.com
Si,  de hecho lo probe y tengo el codigo asi:
IF  ISFLOCKED() *** si esta bloqueada antes
    WAIT "La tabla esta siendo ocupada por otro usuario" windows nowait
 ELSE
   IF FLOCK()  *** bloquea para yo poder ingresar registro nuevo
 
  SELECT contador  FROM formula  ORDER BY contador INTO CURSOR consec
  SELECT consec

  GO bottom
 
  IF RECCOUNT() > 0
   
     consec = contador + 1
   
    ELSE
     consec = 1
  ENDIF
   
    thisform.txtContador.Value = consec
 
  *--- aca el unlock para soltar el registro
    UNLOCK
 
      ENDIF
 ENDIF

mas no se como: 1. saber cuanto tiempo el otro usuario se demorara, ya que si no solo ingresa uno, son dos o mas registros???..
2. sigo en lo mismo, no es que al usar cursorsetprop(buffering,5,mitabla), set multilocks on no tendria que usar flock, o rlock ???.. explicacion por favor!!

Analyzer

unread,
Feb 7, 2014, 12:18:06 PM2/7/14
to vfpl...@googlegroups.com
Ejemplo de FLOCK de la ayuda de VFP8 en Español:

CLOSE DATABASES
OPEN DATABASE (HOME(2) + 'Data\testdata')
USE products  && Opens products table
SET REPROCESS TO 3 SECONDS
SELECT * FROM products INTO TABLE newprods
IF FLOCK( )
*** New product initialization ***
REPLACE ALL in_stock  WITH 0.00
REPLACE ALL on_order WITH 0.00
WAIT 'Initialization Complete' WINDOW NOWAIT
ELSE
*** File is locked, warn user ***
WAIT WINDOW 'Unable to open products file; try again later!' NOWAIT
ENDIF
BROWSE FIELDS in_stock, on_order && Displays newprods table
USE
ERASE newprods.dbf

El set reprocess intenta de nuevo la operación si la tabla estaba bloqueada (para grabar) en el primer intento.

Al decir IF FLOCK() estamos diciendole al VFP: SI Fueposiblebloquearlatabla(), haz el grabado de los datos.



Saludos!


Sandy

unread,
Feb 7, 2014, 12:45:54 PM2/7/14
to vfpl...@googlegroups.com
Entonces quiere decir que el flock solo se utiliza en el boton guardar?, o estoy confundida... ya que yo lo tengo en nuevo y en guardar lo probe mas me decia la tabla esta siendo ocupada y jamas me dejo guardar...




El viernes, 7 de febrero de 2014 10:36:52 UTC-6, Sandy escribió:

Analyzer

unread,
Feb 7, 2014, 12:52:40 PM2/7/14
to vfpl...@googlegroups.com
Sandy,

Te busque esto para leer acerca de buffering. Quizás te de una idea general.
Solo es material de lectura. Ahora vemos si podemos ofrecerte una solución..

Saludos!

Analyzer

unread,
Feb 7, 2014, 12:54:57 PM2/7/14
to vfpl...@googlegroups.com
Mirá este comentario que encontré en un foro:

*** Inicio de la cita

=cursorsetprop("buffering",3)
permite crear un buffer del registro actual en cual puedes modificar y al dar
=tableupdate(.t.) guarda los cambios
=tablerever(.t.) deshace los cambios
en cualquiera de los dos casos el cursorsetprop se desactiva
 
=cursorsetprop("buffering",5)
permite crear un buffer de la tabla actual en cual puedes hacer los cambios en los registros que desees  y al dar
=tableupdate(.t.) guarda los cambios realizados en toda la tabla
=tablerever(.t.) deshace los cambios realizados de toda la tabla
en cualquiera de los dos casos el cursorsetprop se desactiva
Nota:
antes de esto debes de activar en el procedimiento load del formulario
set multilock on (activos los bloqueos automaticos)
set exclusive off
 
y con esto ya no utilices rlock y flock

** Fin de la cita


Saludos!

Sandy

unread,
Feb 7, 2014, 1:25:32 PM2/7/14
to vfpl...@googlegroups.com

Gracias!!.. algunos links ya los estoy leyendo, y si, ya habia leido eso del grupo comunidad vfp... gracias!!


El viernes, 7 de febrero de 2014 10:36:52 UTC-6, Sandy escribió:

Analyzer

unread,
Feb 7, 2014, 1:56:29 PM2/7/14
to vfpl...@googlegroups.com
Si es que trabajas con Ruth en el mismo proyecto quizás te sirva ver este enlace:

https://groups.google.com/forum/?hl=es#!topic/mundovisualfoxpro/f8IsSZMzBlc


Saludos!


Sandy

unread,
Feb 7, 2014, 2:22:11 PM2/7/14
to vfpl...@googlegroups.com
Gracias!!.. estudiamos juntas Ruth y yo, estamos en lo mismo.. solo que son aplicaciones distintas accesando a una misma BD..

yo quiero saber como hacer para que mi aplicacion cuando este Ruth u otro usuario accediendo a la BD me indique que esta ocupada!!... para que desde mi aplicacion yo no realiza nada y espere a que ruth u otro usuario la desbloquee..




El viernes, 7 de febrero de 2014 10:36:52 UTC-6, Sandy escribió:

Analyzer

unread,
Feb 7, 2014, 2:27:55 PM2/7/14
to vfpl...@googlegroups.com
Pues no veo otra forma más que:

1. ISFLOCKED( ) && Eso te dice si está bloqueada la tabla.

2. IF FLOCK()  && Si tuvo exito en bloquear la tabla.

IF FLOCK( )  &&
* Aquí haces los replaces (o updates)
WAIT 'Se efectuaron los reemplazos' WINDOW NOWAIT
ELSE  && Si no tuvo exito al intentar bloquear la tabla
*** El archivo está bloqueado, advertencia para el usuario ***
WAIT WINDOW 'Esta siendo usada por otro usuario. Reintente!' NOWAIT

ENDIF
BROWSE FIELDS in_stock, on_order && Displays newprods table
USE
ERASE newprods.dbf


Saludos!


Analyzer

unread,
Feb 7, 2014, 3:22:48 PM2/7/14
to vfpl...@googlegroups.com
El manual del programador en la parte 5 (Ampliar aplicaciones), Capitulo 17, programar para acceso compartido explica de forma elegante todo eso de los bloqueos.

Dice en parte:

Sugerencia Si desea comprobar el estado de bloqueo de un registro en la sesión sin bloquear
el registro, use la función ISRLOCKED( ) o ISFLOCKED( ).


Si falla el intento de bloquear un registro o una tabla, el comando SET REPROCESS y la rutina de
error actual determinarán si vuelve a intentarse el bloqueo.
SET REPROCESS afecta al resultado de
un intento de bloqueo sin éxito. Puede controlar el número de intentos de bloqueo o el período de
tiempo durante el cual se intenta un bloqueo mediante SET REPROCESS.
Ejemplo: bloqueo manual
El ejemplo siguiente abre la tabla customer para acceso compartido y utiliza FLOCK( ) para intentar
bloquearla. Si la tabla se bloquea con éxito, REPLACE ALL actualizará todos sus registros.
UNLOCK libera el bloqueo de archivo. Si el archivo no puede bloquearse porque otro usuario haya
bloqueado el archivo o uno de sus registros, se mostrará un mensaje.
SET EXCLUSIVE OFF
SET REPROCESS TO 0
USE customer && Abrir tabla compartida
IF FLOCK()
REPLACE ALL contact ; && Reemplazar y desbloquear
WITH UPPER(contact)
UNLOCK
ELSE && Mensaje de salida
WAIT "Otro usuario está utilizando el archivo." WINDOW NOWAIT
ENDIF

Para desbloquear un registro que se ha bloqueado automáticamente, sólo necesitará mover el puntero
de registro, aunque haya establecido MULTILOCKS ON. && El bloqueo automático es que g

No obstante, deberá eliminar explícitamente el bloqueo de un registro que haya bloqueado manualmente; mover el puntero de registro no es suficiente

El tercer botón que está arriba donde dice Save.

Saludos!

Sandy

unread,
Feb 7, 2014, 3:35:28 PM2/7/14
to vfpl...@googlegroups.com
Gracias Analyzer,,, estoy leyendo el manual del programador 5 parte :D




El viernes, 7 de febrero de 2014 10:36:52 UTC-6, Sandy escribió:

Analyzer

unread,
Feb 7, 2014, 3:42:00 PM2/7/14
to vfpl...@googlegroups.com
Al final, a ver si no te desanimas de usar los buffers esos y terminas usando los comandos para "simulación" de buffers y  variables de memoria.

Si te interesa pregunta acerca de:

Scatter - Gather - Scatter Name

Forma usual de usar Scatter Name
https://groups.google.com/forum/#!topic/publicesvfoxpro/yVhZIWobss4


Saludos!


Analyzer

unread,
Feb 7, 2014, 3:55:49 PM2/7/14
to vfpl...@googlegroups.com
Si el caso fuera usar scatter gather, observa este comentario de tesys en este enlace:

https://groups.google.com/forum/#!topic/publicesvfoxpro/SqGtvh8W_io

** Inicio de la cita

Supongo que no tienes mucha experiencia en esto de RLOCK()  y FLOCK().

Por ello te recomiendo lo siguiente.
Supongamos que quieres modificar un REGISTRO.
1.- Levanta los datos de los CAMPOS en variables.
    Para ello NO NECESITAS NINGÚN  Lock().
2.- Realiza todas las modificaciones que desees sobre las variables.
3.- Cuando este TODO OK, recién allí realiza las modificaciones en el archivo.
    Acá funcionan los LOCK().

Es común que los programadores se equivoquen y realicen un RLOCK() en el punto 1.
Que puede ocurrir ?
1.- Un usuario pretendió modificar.
El programa realizo el RLOCK()
2.- El usuario se fue a almorzar.
3.- Volvió a las 2 horas.

El registro o el archivo-tabla estuvo BLOQUEADO y no se pudieron realizar operaciones.
Esto es valido también para los APPEND BLANK
No trabajes SOBRE LOS CAMPOS DE LAS TABLAS.

** Fin de la cita



Saludos!

Sandy

unread,
Feb 7, 2014, 6:23:49 PM2/7/14
to vfpl...@googlegroups.com
Analyzer, e leido casi todos los articulos que la web me ha proporcionado sobre gather memvar.. y en todos los articulos dicen que son comandos de fox 6 y que en el 9 se hace uso ya de todo lo que es las sentencias sql, en el caso de nuevo registro insert into, etc..

En tus comienzos supongo que tuviste los mismos pegones que uno tiene, hay mucha informacion mas de ese monton de informacion lo que uno hace es probar y haci ir armando lo que se desea por medio de codigo.

Podrias indicarme cual es la forma mas idonea para realizar los bloqueos, e visto que tambien sugieren las transaciones, con begin transactions  ... end transactions

Gracias por tus aportes!!


El viernes, 7 de febrero de 2014 10:36:52 UTC-6, Sandy escribió:

matrix.si

unread,
Feb 8, 2014, 5:46:30 AM2/8/14
to vfpl...@googlegroups.com
yo lo haria asi
set reproccess to 1
select tabla
x=flock()
if x=.f.
messagebox("Tabla bloqueada por otro usuario"...)
return
endif
.. proceso
..proceso
unlock

jhernancanom

unread,
Feb 8, 2014, 11:48:15 AM2/8/14
to vfpl...@googlegroups.com

Hola.
Si quieres hacerlo en Nuevo, puedes hacerlo... NO SE RECOMIENDA. Debería ser el Grabar.

Pero lo importante es que si lo haces en Nuevo, en alguna parte deberías hacer UNLOCK. No se sabe si lo estás haciendo (sólo dices que haces FLOCK en Nuevo, pero no hablas de UNLOCK).

La recomendación es que lo hagas en el botón Grabar. La combinación ISFLOCKED/FLOCK luce bien, pero te recomiendo agregar un ELSE al FLOCK, pero veo que tienes un malentendimiento de ISFLOCKED: es a la inversa de lo que piensas.

¿Cuánto se demora un usuario escribiendo? Eres tú quien lo sabe, pero no necesitas saberlo: debes programar a la defensiva.
Te voy a dar un tip (alquien quizá me maldiga, pero lo haré pues yo también programo con FLOCK/RLOCK/UNLOCK y NUNCA he tenido problemas (considero que tengo bien definido mi escenario para prevenir problemas que se van a comentar aquí).


select CLIENTES  && por ejemplo

** suprime ISFLOCKED()
**
**IF  ISFLOCKED()  && si esta bloqueada antes
**    WAIT "La tabla esta siendo ocupada por otro usuario" windows nowait
** 
** si ISFLOCKED() devuelve verdadero, no significa que "otro usuario" la tiene bloqueada, sino que "eres tú misma" quien la tienes bloqueada.
** 
**
**ELSE 
   local K
   K=seconds()
   do while .not. FLOCK()  && bloquea para yo poder ingresar registro nuevo
      if seconds()-K>5000  && (creo que son milésimas) se debe hacer pruebas para encontrar un valor adecuado
         exit
      endif
   enddo
   if flocked()
      **
      **
      ** aquí haces todo lo que necesites
      **
      **
      **

      *--- aca el unlock para soltar el registro
      UNLOCK 

   else
       Messagebox("No se pudo bloquear el archivo en 5 segundos")
   endif

**ENDIF

Para evitar demoras en el bloqueo, y que otro usuario "se quede" con el registro, sólo bloqueas al grabar (botón Grabar) y haces el UNLOCK al terminar de grabar.

Si otro usuario ya tiene el registro bloqueado, el ciclo DO WHILE que te propongo hará la espera hasta que lo desbloquee--- PERO DEBES SABER QUE SI LA GRABACION ES EXITOSA la demora será de milésimas de segundo y no lo notarás NUNCA aunque dos o tres o cuatro usuarios accedan al mismo tiempo (((MIENTRAS LA RED SEA DE VELOCIDAD NORMAL, Y LA GRABACIÒN NO TENGA MUCHISIMAS instrucciones o campos))) y evidentemente uses técnicas adecuadas de programación.

Te repito: Si otro usuario ya tiene el registro bloqueado, el ciclo DO WHILE que te propongo hará la espera hasta que lo desbloquee (qeu debería ser de milésimas de segundo).

Analyzer

unread,
Feb 9, 2014, 1:24:04 AM2/9/14
to vfpl...@googlegroups.com
El scatter gather pueden hacerla de buffer en una técnica alternativa a usar buffers de registros, no buffers de tablas.

Aun en la versión 9 pueden ser usados, si se usan correctamente, sin inconvenientes. En especial si se usa scatter name.

¿Cómo entender su uso?

Abra una tabla cualquiera.

teclee browse en la ventana de comandos para observar que tiene.

Luego vaya al registro que desee copiar. Ej. copiar el registro 3 al final del archivo.

USE mitabla IN 0
go NumerodelRegistro a copiar
SCATTER memvar  && Esto manda a variables de memoria el registro de la tabla.
DISPLAY MEMORY LIKE *  && Aquí puede ver que datos tiene cada variable.
GO bottom  
INSERT INTO mitabla FROM memvar  && Esto inserta desde las variables en memoria el registro copiado al nuevo registro.
BROWSE

Las variables de memoria pueden verse con ? m.micampo porque VFP les antepone una "m" y un "punto" y se llaman igual que los nombres de los campos.

Obvio que si la operación no es abrir un nuevo registro no se usaría insert into. Por algunas razones que se han explicado en los foros, se recomienda más usar scatter name en lugar de solo scatter.



Saludos!


Analyzer

unread,
Feb 9, 2014, 1:27:53 AM2/9/14
to vfpl...@googlegroups.com
>El 9 de febrero de 2014, 0:24, Analyzer <thenewin...@gmail.com> escribió:
El scatter gather pueden hacerla de buffer en una técnica alternativa a usar buffers de registros, no buffers de tablas.

Lee en el manual del programador la diferencia entre buffer de tabla y buffer de registro. También hay otras dos combinaciones: pesimista y optimista.


Saludos!

Sandy

unread,
Feb 10, 2014, 10:10:05 AM2/10/14
to vfpl...@googlegroups.com
matrix, jhernancanon, analyzer!!.. muchas gracias por su ayuda!! y sus sugerencias!...

Por que recomiendan en guardar?, si se supone que en nuevo es que realizara el proceso de seleccinar un id, tomar los datos de los textbox y realizar las operaciones para luego en guardar solo darle tableupdate... no entiendo, mas si e visto que lo han recomendado mucho, yo lo e probado. mas si alguien guarda antes que yo, a mi me hace que guardo mas no me guarda!... ya que consulto la BD y mi registro que supuestamente lo guardo no esta, en el lugar de el esta otro!! que se lo inserto otro usuario


Mil gracias si, por sus comentarios



El viernes, 7 de febrero de 2014 10:36:52 UTC-6, Sandy escribió:

Saúl Piña

unread,
Feb 11, 2014, 9:51:56 AM2/11/14
to vfpl...@googlegroups.com
Saludos, miralo de esta forma, cuando das clic en nuevo, solo haz que el usuario vaya capturando los datos (y en ese momento no tomes un id, sino hasta donde estés preparado para guardar), y solo en el momento de guardar utiliza las opciones de bloqueo si lo deseas, yo por lo general, hago lo siguiente:


1. Clic en nuevo (solo muestro un label en donde debe aparecer la id con la leyenda "Nuevo"
2. Al momento de guardar, busco en la tabla cual es el último id guardado, inmediatamente genero consecutivo y finalmente guardo, todo en tres lineas de codigo.

Suerte.

Sandy

unread,
Feb 11, 2014, 12:30:09 PM2/11/14
to vfpl...@googlegroups.com
Gracias Saul!.. de hecho lo tengo asi:
en nuevo solo habilito todos los textbox para capturar los datos que el usuario va ingresar

y en el boton guardar mando una consulta donde me tome el ultimo id y lo incremento, luego se lo pinto al textbox.

luego tengo =TABLEUPDATE(.T.,.T.,"cestadovfp")




El viernes, 7 de febrero de 2014 10:36:52 UTC-6, Sandy escribió:

Analyzer

unread,
Feb 11, 2014, 12:37:31 PM2/11/14
to vfpl...@googlegroups.com
 =TABLEUPDATE(1,.T.,"cestadovfp")

Cambia la primeta .T. por el 1 y prueba..

Saludos!


Hernan Cano

unread,
Feb 13, 2014, 5:28:12 PM2/13/14
to vfpl...@googlegroups.com
Sandy:

>>> ...  a mi me hace que guardo mas no me guarda!...

Lo lamento, pero no entiendo.

>>>... de hecho lo tengo asi:

en nuevo solo habilito todos los textbox para capturar los datos que el usuario va ingresar
y en el boton guardar mando una consulta donde me tome el ultimo id y lo incremento, luego se lo pinto al textbox.
luego tengo =TABLEUPDATE(.T.,.T.,"cestadovfp")

Así es como debemos programar. Si estás obteniendo resultados incorrectos, entonces estás haciendo algo más que no nos estás diciendo.

Mejor dicho si no nos muestras el código no podremos ayudarte.

El código realmente no es imperativo que lo expongas, pues en base a lo "teórico" que expongas y expongamos, tú deberías avanzar; pero la frase "me hace que guarda y no guarda" no tiene sentido.


Sandy

unread,
Feb 14, 2014, 2:58:39 PM2/14/14
to vfpl...@googlegroups.com
Gracias Jhernan, osea que segun la aplicacion guardaba y al verificar en la base de datos no guardaba el dato... ya guarda si, solo me daba un error a la hora de modificar, me incrementaba el id cosa que no debaria de ser, entonces decidi ponerlo en el boton nuevo el incremento.

Me guarda bien si, me modifica y elimina.. gracias por sus comentarios!

Saludos!

Hernan Cano

unread,
Feb 14, 2014, 9:25:13 PM2/14/14
to vfpl...@googlegroups.com
Recuerda: 
No se incrementa el consecutivo a pulsar en Nuevo. Sí se incrementa el consecutivo a pulsar en Grabar.

De esta forma no se "incrementa" extrañamente.

Para Modificar, no utilices ISFLOCKED; quizá éso era el problema.
Reply all
Reply to author
Forward
0 new messages