FoxPro/Visual FoxPro - Para Fidel

   
Vista:

Para Fidel

Publicado por Alvaro Garcia (5 intervenciones) el 04/11/2012 00:47:25
Muchas gracias Fidel por tu ayuda y perdona que te moleste nuevamente.

Tal y como me indicaste he puesto el siguiente código y me funciona bien, pero solo en los campos de tipo carácter; el campo "Marcado" que es de tipo logico, no me lo actualiza , he probado a ponerlo de tipo numérico y tampoco lo consigo.
Saludos.



* BtnSelect
Thisform.Grid1.RecordSource= ""

SELECT *,RECNO() FROM TABLAS!ARTICULOS WHERE Articulos.codigo_fam = (mCodFaminf);
into CURSOR miCursor READWRITE

with Thisform.grid1
.RecordSource= 'micursor'
.column1.ControlSource = 'micursor.famycod'
.column2.ControlSource = 'micursor.Marcado'
.column3.ControlSource = 'micursor.Descripcio'
.column4.ControlSource = 'micursor.referencia'
endwith

Thisform.Refresh



* BtnActualizar
select Micursor
cExp="Exp_"+ltrim(str(fcount() ))

* Actualizar con el número de registro
* Suponiendo que no se utiliza CursorAdapter ( o sea, utilizando bloque manual)

Select Micursor
SCAN
nRegistro=Evaluate(cExp)
Scatter MEMO TO gaArray
if nRegistro = 0
INSERT INTO ARticulos FROM ARRAY gaArray
else
SELECT ARTICULOS
GO nRegistro
IF RLOCK()
GATHER FROM gaArray
endif
ENDIF

ENDSCAN

SELECT ARTICULOS
UNLOCK
TABLEUPDATE(.T.)
THISFORM.Refresh
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

Para Fidel

Publicado por Fidel (321 intervenciones) el 05/11/2012 16:42:31
No veo una razón por la que los campos numéricos se comporten distinto de otros en una actualización con gather, salvo para los casos específicos (campos memo , por ejemplo).

Lo único que veo en el código, aunque no sé si afecta es:
Si tomas SCATTER ... MEMO, deber utilizar GATHER from Array garray MEMO.
Si no hay campos memo, puedes omitir la cláusula MEMO.

También, en remplazo de ARRAY, puedes utilizar MEMVAR

Select Micursor
SCAN
nRegistro=Evaluate(cExp)
Scatter MEMO MEMVAR
if nRegistro = 0
INSERT INTO ARticulos FROM MEMVAR
else
SELECT ARTICULOS
GO nRegistro
IF RLOCK()
GATHER MEMVAR MEMO
endif
ENDIF

ENDSCAN

En general MEMVAR puede ser más rápido que ARRAY. Fijate los cambios en la sintaxis.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Para Fidel

Publicado por Alvaro Garcia (5 intervenciones) el 05/11/2012 21:53:36
¡Por fin funciona bien!
He puesto los cambios que me has hecho y todo va perfecto.
Muy agradecido.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Para Fidel

Publicado por Fidel (321 intervenciones) el 05/11/2012 22:32:30
Alvaro:
Un comentario sobre bloqueos.
Es importante decidir qué tipo de bloqueo se utiliza en las tablas compartidas.
Básicamente, hay dos opciones (en realidad hay más, pero poco relevantes)
En el ejemplo supongo que hay una tabla llamada PERSONAL.DBF que tiene, por lo menos, dos campos: NOMBRE (C) y ACTIVO (L)

SELECT PERSONAL
INSERT INTO PERSONAL (NOMBRE,ACTIVO) VALUES ("PEPE",.F.)
UNLOCK
&& Le agrego un registro y luego:
1) Bloqueo manual de registros y tablas.
lcNombre="Smith"
llActivo=.T.
SELECT PERSONAL
IF RLOCK()
REPLACE NOMBRE WITH LCNOMBRE,;
ACTIVO WITH LLActivo
UNLOCK
ENDIF
Messagebox("Valor de 'Nombre'="+trim(nombre))

2) Bloqueo automático
SET MULTILOCKS ON && Debe estar en on para almacenar tablas en búfer.
= CURSORSETPROP('Buffering', 5, 'PERSONAL' ) && Activa el almacenamiento de tablas en búfer.
* AGREGA UN REGISTRO A LA TABLA
INSERT INTO PERSONAL (NOMBRE,ACTIVO) VALUES ('Smith',.T.)
select personal
Messagebox("Valor de 'Nombre'="+trim(nombre))
REPLACE nombre WITH 'Jones'
nMess=Messagebox("<RSP/>Valor de 'Nombre'="+trim(nombre)+CHR(13);
+"Desea Grabar?",4,"Grabando")
if nMess=6
= TABLEUPDATE(.T.) && Graba los cambios.
else
= tablerevert()
endif
= CURSORSETPROP('Buffering',1, 'PERSONAL' ) && DesActiva el almacenamiento de tablas en búfer.
Messagebox("Valor de 'Nombre'="+trim(nombre))

Si utilizas RLOCK() y UNLOCK(), no funciona TableUpdate()
Si utilizas CursorSetProp("Buffering",5,"PERSONAL") estás indicando que la tabla personal se emplee con almacenamiento optimista en buffer. Puedes escribir lo que quieras, solo se grabará en la tabla cuando ejecutes TABLEUPDATE(.T.). Y puedes quitar todo lo agregado con TableRevert(). Y en este caso, no debes utilizar LOCK(), RLOCK() ni UNLOCK.
Los que trabajan con tablas asociadas a una base de datos (DBC) pueden utilizar TRANSACTION que permite controlar un ciclo de actualización y revertirlo si falla en alguna parte. Esto no funciona para tablas libres.

La mayoría de los programadores experimentados (no es mi caso) se deciden por utilizar en sus formularios:
Crear el entorno de datos
.BufferMode=2
.DataSession=2
DataEnvironment.Cursor.BufferModeOverride = 5
Y luego se confirman o desechan cambios con TableUpdate(.t.) y TableRevert respectivamente.
Esto les permite trabajar directamente con los campos de las tablas del entorno de datos sin tener que preocuparse por los bloqueos. Con Buffering=5 nunca están bloqueados los registros hasta que se indica TableUpdate (con SET MULTILOCKS ON).
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Para Fidel

Publicado por Fidel (321 intervenciones) el 06/11/2012 00:57:01
Perdón Alvaro
Hay una cosa importante.
Si utilizas RLOCK() y UNLOCK, corresponde utilizar FLUSH
El comando FLUSH consigue bajar el cache y te asegura que, ante un corte de energía, los registros sigan estando en la tabla. De lo contrario, es posible que Windows no actualice realmente las tablas, sino que actualice su versión en buffer. Si se corta la luz y las tablas no se cierran, pueden ocurrir errores de índices y muy probablemente faltará información.
1) Bloqueo manual de registros y tablas.
lcNombre="Smith"
llActivo=.T.
SELECT PERSONAL
IF RLOCK()
REPLACE NOMBRE WITH LCNOMBRE,;
ACTIVO WITH LLActivo
UNLOCK
ENDIF
FLUSH && utiliza un solo FLUSH al final de una secuencia de actualización.

En el método de bloqueo automático, no debe utilizarse FLUSH, porque esta función la realiza TableUpdate(.t.)
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Para Fidel

Publicado por Alvaro Garcia (5 intervenciones) el 06/11/2012 22:03:57
Muchas gracias Fidel por la lección magistral, tomo nata, me temo que necesito algunas mas.
Saludos.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar