Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Firebird e Interbase (https://www.clubdelphi.com/foros/forumdisplay.php?f=19)
-   -   problema con visibilidad de transacciones (https://www.clubdelphi.com/foros/showthread.php?t=62283)

Galahad 15-12-2008 10:47:21

problema con visibilidad de transacciones
 
saludos..., estoy creando un mantenimiento en el que pretendo que
uno de los campos claves (codigobanco) se autoasigne en el Triguer de la base de datos 'beforeinsert'.
1.-) Cuando creo un nuevo registro en el mantenimiento, en la aplicación cliente no veo el valor de dicho campo clave en ningun momento, es decir
cuando creo un nuevo registro el valor del campo clave asignado por el triguer aparece vacio, incluso después de grabar el campo tambien aparece vacio, en cámbio, cuando cierro y abro la aplicación si que aparece automáticamente el registro con el valor asignado por el triguer correctamente. De hecho, incluso despues de grabar dicho nuevo registro ,hojeando la base de datos en el 'sql Manager' observo que se ha generado correctamente el valor del campo.
Utilizo el componente tfibdataset de los fibplus
2.-) Por otro lado, si en el evento afterinsert de dicho componente, intento asignar el foco de edifición en un dbedit con por ejemplo 'editnombre.setfocus', recibo un accesviolation ¿?

este es el código de la base de datos.

Código:

CREATE TABLE FAC_MAE_FABAN (
  EMPRESA VARCHAR(3) CHARACTER SET NONE NOT NULL COLLATE NONE,
  CODIGOBANCO INTEGER NOT NULL,
  NOMBREBANCO VARCHAR(40) CHARACTER SET NONE COLLATE NONE,
  ENTIDAD VARCHAR(4) CHARACTER SET NONE COLLATE NONE,
  SUCURSAL VARCHAR(4) CHARACTER SET NONE COLLATE NONE,
  DC VARCHAR(2) CHARACTER SET NONE COLLATE NONE,
  CUENTA VARCHAR(10) CHARACTER SET NONE COLLATE NONE,
  POBLACION VARCHAR(40) CHARACTER SET NONE COLLATE NONE,
  DIRECCION VARCHAR(40) CHARACTER SET NONE COLLATE NONE,
  PROVINCIA VARCHAR(20) CHARACTER SET NONE COLLATE NONE,
  TELEFONO DEF_TFNO_FAX,
  FAX DEF_TFNO_FAX,
  OBSERVACION BLOB,
  CUENTACONTABLE VARCHAR(8) CHARACTER SET NONE COLLATE NONE,
  CLAVELIBROPOSICION VARCHAR(10) CHARACTER SET NONE COLLATE NONE,
  RIESGOMAXIMOPAGARES NUMERIC(11, 2) DEFAULT 0.0,
  RIESGOMAXIMORECIBOS NUMERIC(11, 2) DEFAULT 0.0,
  RIESGOMAXIMO COMPUTED BY (RIESGOMAXIMORECIBOS+RIESGOMAXIMOPAGARES));


ALTER TABLE FAC_MAE_FABAN ADD CONSTRAINT PK_FAC_MAE_FABAN PRIMARY KEY (EMPRESA,CODIGOBANCO);


CREATE INDEX FAC_MAE_FABAN_IDX1 ON FAC_MAE_FABAN(NOMBREBANCO);


SET TERM ^ ;



SET TERM ^ ;

CREATE TRIGGER FAC_MAE_FABAN_BI FOR FAC_MAE_FABAN
ACTIVE BEFORE INSERT
POSITION 0
AS
DECLARE VARIABLE NULTIMO INTEGER DEFAULT 0;
BEGIN
   
    nultimo = 0;     
    if (new.codigobanco is null) then
    begin   
      select max( codigobanco ) from fac_mae_faban Where (empresa = new.empresa) into :nultimo;
      nultimo = nultimo+1;
      new.codigobanco = nultimo;
    end 
 
   
END^

SET TERM ; ^

a ver si me pueden ayudar, estoy dandole vueltas, he imagino que tiene algo que ver con la visiblidad de las transacciones, pero no consiguo identificar el problema.

Galahad 15-12-2008 16:52:38

valores por defecto
 
me contesto a mi mismo....

En cuanto a la visiblidad , bueno, he podido solucionarlo simplemente cerrando y volviendo a abrir el dataset, el único problema es que al hacerlo, por defecto el dataset se desplaza al último registro, me gustaria conseguir que si por ejemplo el usuario confirma los cambios de edición del registro con el código 25, al confirmar los cámbios no se desplaze al registro con el código 41 (último).
Por otro lado, sigo sin conseguir visualizar el valor asignado por el triguer 'before insert' hasta que hago el post..., he estado haciendo pruebas con los componentes 'fibevents', pero me doy cuenta de que su función principal es la
'refrescar' los contenidos de la base de datos a otros clientes conectados.
saludos,, sigo buscando soluciones...

Galahad 16-12-2008 12:55:49

resuelto con stored procedure
 
simplemente comentar que estaba equivocado, los triggers before insert se ejecutan justo antes de efectuar la inserción del registro, no para suministrar valores por defecto iniciales que era mi intención.
al final lo he solucionado, llamando a un stored procedure desde el evento afterinsert del componente tfibdataset.
me queda por resolver el hecho de recuperar el puntero después de guardar una edición de un registro, al cerrar y abrir el componente, se posiciona en el último registro.
saludos...

boreg 17-12-2008 06:28:42

¿Probaste con refresh?, con esto te refresca el registro en el que estás posicionado sin actualzar todo, de otra forma para posicionarte en el registro que quieres utiliza el locate de tu componente.

Saludos

Galahad 17-12-2008 09:22:20

refresh
 
Cita:

Empezado por boreg (Mensaje 331245)
¿Probaste con refresh?, con esto te refresca el registro en el que estás posicionado sin actualzar todo, de otra forma para posicionarte en el registro que quieres utiliza el locate de tu componente.

Saludos

gracias por contestar, bueno, realmente el refresh, funciona....., es decir el cursor se queda el registro editado, el problema es que al crear un nuevo registro,si por ejemplo he insertado el código 4,, una vez insertado, veo los registros (en un grid) con la siguiente codificación : códigos 4,1,2,3 ¿?.
al cerrar y volver a abrir el mantenimiento, aparece todo correcto

al final lo he solucionado haciendo
dataset.close;
dataset.open;
dataset.locate( 'registrox') // solo para los casos de edición.

aunque funciona, imagino que el cerrar y volver a abrir el conjunto de datos no es la mejor solución por el mayor consumo de registros que representa:

nota: en el efecto afterpost del dataset tengo la siguiente cadena

tpfibdataset( dataset ).transaction.commitretaining;

gracias por la ayuda...

Sick boy 17-12-2008 11:04:46

Hola,

empezar diciendo que no uso los FIb, uso MDO, pero son similares.

Cita:

simplemente comentar que estaba equivocado, los triggers before insert se ejecutan justo antes de efectuar la inserción del registro, no para suministrar valores por defecto iniciales que era mi intención.
No estoy de acuerdo. Precisamente yo lo uso para eso.
Tu mismo dices que te funciona, pero que no ves el dato añadido hasta que vuelves a abrir el dataset.
Entonces, asignar el valor funciona, el problema es que no lo ves en ese momento.

¿Estas seguro de que es la misma transaccion?? Los FIb tienen un componente de transaccion independiente del dataset??
Has comprobado la opcion (AutoCommit) por defecto del dataset??

Cita:

al final lo he solucionado haciendo
dataset.close;
dataset.open;
dataset.locate( 'registrox') // solo para los casos de edición.

aunque funciona, imagino que el cerrar y volver a abrir el conjunto de datos no es la mejor solución por el mayor consumo de registros que representa:
Hombre, no es que este mal, pero yo nunca lo haria. Mira la documentacion de locate para ver como trabaja.
Si te preocupa el close y open, te deberia preocupar mucho más el locate, que no utiliza ningun indice para hacer la busqueda, y se trae todos los datos del dataset hasta encontrar el que coincide.

Creo que la opcion de usar bookmarks puede servirte mejor.

Cita:

nota: en el efecto afterpost del dataset tengo la siguiente cadena

tpfibdataset( dataset ).transaction.commitretaining;
Tengo entendido que commitretaining historicamente no ha funcionado muy bien. Yo apenas lo uso.
Si funciona bien, lo que hacer es un commit de la transaccion, más la apertura del dataset asociado (y quizas me equivoque, pero creo que deberia colocar el cursor en el punto donde estaba anteriormente), lo cual efectivamente consume recursos, tiempo y red.

Puede que estes haciendo otras cosas que interfieran, si puedes poner más informacion, el codigo que utilizas, etc...

Galahad 17-12-2008 12:44:03

Cita:

Empezado por Sick boy (Mensaje 331256)
Hola,

No estoy de acuerdo. Precisamente yo lo uso para eso.
Tu mismo dices que te funciona, pero que no ves el dato añadido hasta que vuelves a abrir el dataset.
Entonces, asignar el valor funciona, el problema es que no lo ves en ese momento.

bueno, aqui el tema es que tenia yo una confusión de conceptos, por derivación de paradox, hasta ahora el afterinsert erá el evento en el que
asignaba los valores por defecto que vé el usuario para empezar a crear un registro nuevo, error, el triguer before insert es el evento en el que se asignan los valores por defecto antes de grabar el registro.
por eso no me sirve el trigguer para dejar estos valores por defecto cuando (desde un mantenimiento) se crea un registro nuevo.

Cita:

Empezado por Sick boy (Mensaje 331256)
¿Estas seguro de que es la misma transaccion?? Los FIb tienen un componente de transaccion independiente del dataset??
Has comprobado la opcion (AutoCommit) por defecto del dataset??

si, los fib tienen un componentes de transacción independiente del dataset, tengo una sola transacción, si que tiene la opción autocommit, la tengo a false, el caso es que he vuelto a instalar el servidor de firebird y... FUNCIONA !! :), es decir ahora tengo el siguiente código en el evento datasetafterpost:
tpfibdataset( dataset).transaction.commitretaining;
dataset.refresh
es decir , ya no hago el :
dataset.close;
dataset.open;
dataset.locate( ...),
y funciona perfectamente, es decir , no tengo necesidad de volver a abrir la fuente de datos..

Cita:

Empezado por Sick boy (Mensaje 331256)
te deberia preocupar mucho más el locate, que no utiliza ningun indice para hacer la busqueda, y se trae todos los datos del dataset hasta encontrar el que coincide.

creo el locate utiliza los índices para optimizar los índices ,por lo que no son una mala opción a utilizar si existen indices creados a utilizar (que alguién me rectifique si estoy equivocado


Cita:

Empezado por Sick boy (Mensaje 331256)
Tengo entendido que commitretaining historicamente no ha funcionado muy bien. Yo apenas lo uso.
Si funciona bien, lo que hacer es un commit de la transaccion, más la apertura del dataset asociado (y quizas me equivoque, pero creo que deberia colocar el cursor en el punto donde estaba anteriormente), lo cual efectivamente consume recursos, tiempo y red.

entiendo que en el contexto de un mantenimiento (uso intensivo de altas/bajas/modificaciones), es más aplicable el concepto del commitretaining,porque se requiere que la tabla quede abierta, en este
hilo hay un comentario al respecto, no obstante me gustaria conocer más opiniones al respecto.

un saludo

Sick boy 17-12-2008 13:47:40

Cita:

bueno, aqui el tema es que tenia yo una confusión de conceptos, por derivación de paradox, hasta ahora el afterinsert erá el evento en el que
asignaba los valores por defecto que vé el usuario para empezar a crear un registro nuevo, error, el triguer before insert es el evento en el que se asignan los valores por defecto antes de grabar el registro.
por eso no me sirve el trigguer para dejar estos valores por defecto cuando (desde un mantenimiento) se crea un registro nuevo.
Ufff, si no lo entiendo mal, tu incias los valores del siguiente registro justo despues de crear el anterior????
En mi opinion, esta mal, yo no lo haria.
Para valores por defecto, usa DEFAULT al crear la tabla.O inicialos en el evento de insercion, pero no añadas un registro extra, pensando que luego lo utilizaras.
Si no lo utilizas tendrás que borrarlo, o dejarias registros sin datos.

Cita:

tengo una sola transacción, si que tiene la opción autocommit, la tengo a false,
En que parte de tu codigo haces el commit???
Sigue estando en el AfterPost??

Cita:

creo el locate utiliza los índices para optimizar los índices
Si lo entendiese lo discutiria. Me reafirmo en no usar locate.

Cita:

entiendo que en el contexto de un mantenimiento (uso intensivo de altas/bajas/modificaciones)
Lo siento, pero no se que significa un mantenimiento. Probablemente en españa tenga otro nombre, si me explicas el concepto seguro que te entenderemos.
A cuantas modificaciones por segundo se refiere "el uso intensivo"??

Y por cierto, actualmente no tienes ningun problema, verdad??

PD: Cuando digo que algo esta bien o esta mal, es mi opinion, cada uno despues hace lo que le parece mejor.

RolphyReyes 17-12-2008 14:39:50

Saludos.

Por lo que veo te estas complicando con el uso de los FIBPlus, ellos son hasta ahora los únicos componentes que utilizan el concepto de dos transacciones (Read/Write) lo que los hacen potentes para desarrollo Cliente/Servidor.

Te recomiendo visitar artículos y leer sobre las transacciones con FIBPlus.

El componente TpFIBDatabase tiene dos propieades DefaultTransaction y DefaultUpdateTransaction y a su vez el TpFIBDataSet tiene Transaction y UpdateTransaction. Las primera de ambos indica la transacción que utilizara para la lectura y la segunda la de escritura. Por ende debes de poner en tu DataModule dos componentes TpFIBTransaction configurados adecuadamente.

Así en el TpFIBDataSet en la propiedad Options marcas True la opción poRefreshAfterPost teniendo en cuenta la propiedad RefreshTransaction indique tkReadTransaction , con esto el componente actualizara la transacción larga (Read) la que indicaste en Transaction.

Particularmente utilizo la opción de AutoCommit para mantenimientos, esta opción hace por ti el Commit en la transacción de Escritura y con la opción que ya te mencione poRefreshAfterPost te refrescara la transacción.

Espero haberte ayudado....

Galahad 17-12-2008 15:35:34

mantenimiento
 
a ver si me explico mejor..

Cita:

Empezado por Sick boy (Mensaje 331272)
Ufff, si no lo entiendo mal, tu incias los valores del siguiente registro justo despues de crear el anterior????

el contexto es el de un mantenimiento (pantalla típica de programa de gestión para dar de alta,modificar o borrar por ejemplo clientes). yo hasta ahora, en paradox, cuando el usuario empieza a completar por ejemplo un nuevo cliente, busco él último código existente en la bd y le pongo el codigo siguiente a la vista (siempre trabajando sobre componentes dbware), claro, no puedo hacer esta operación de 'busqueda del codigo que le toca al nuevo cliente' en la claúsula DEFAULT, y tampoco puedo hacerla en el Trigger before insert, porque este evento se activa cuando el usuario 'confirma/graba' los datos del nuevo cliente.
Pero bueno, eso ya ha quedado solucionado con un stored procedure desde la parte del cliente.

Cita:

Empezado por Sick boy (Mensaje 331272)
En que parte de tu codigo haces el commit???
Sigue estando en el AfterPost??

si, al final he dejado esto,,
dataset.commit;
dataset.close;
dataset.open;
dataset.locate( ...)
a mi tampoco me gusta el locate,, de hecho nunca lo he utilizado en mis programas con paradox, pero...., está es la única manera que he encontrado de que cuando acabo de editar un registro y confirmo los cambios, al usuario se le quede en pantalla el registro modificado (al hacer el commit se cierra el juego de datos, y al hacer el open el 'puntero' se queda en el primer registro). He probado los bookmarks, pero no funcionan.


Cita:

Empezado por Sick boy (Mensaje 331272)
Lo siento, pero no se que significa un mantenimiento. Probablemente en españa tenga otro nombre, si me explicas el concepto seguro que te entenderemos.
A cuantas modificaciones por segundo se refiere "el uso intensivo"??

yo tambien soy de españa.,,, (alicante)..., creo que ya he explicado para mí lo que es un mantenimiento.., a este particular, antes has comentado que no utilizas componentes dbware,, en este tipo de procesos de alta,borrado,modificaciones, como lo haces ?, ¿ vuelcas un único registro sobre los por ejemplo edits del form y haces que al navegar por ejemplo con una serie de botones se vaya cargando un único registro en dichos edits ?.
yo hasta ahora siempre he utilizado componentes dbware, y me preocupa el hecho de que voy a tener algunas tablas grandes (30.000 registros), me temo que si utilizo la estructura anterior de que cuando grabo un registro nuevo hago 'dataset.close - dataset.open', me estoy trayendo al cliente los 30.000 registros, no es algo nada óptimo me temo, además los componentes fibplus no tienen componentes dbware en los que se pueden limitar el número de registros que digamos se puedan 'cargar' por cada petición de refresco del cliente por ejemplo.
disculpa sea tan pesado , pero es que tengo que cambiar muchas aplicaciones de paradox a firebird, unos cuantos centenares de forms y ya que voy a estar como mínimo un año , pretendo que la base principal sea lo mejor posible.

Cita:

Empezado por Sick boy (Mensaje 331272)
Y por cierto, actualmente no tienes ningun problema, verdad??

bueno, la cuestión es que ahora mismo, el mantenimiento, funcionar , funciona, pero claro antes de utilizar este mantenimiento como plantilla de otros 200-300 que voy a tener que hacer ,quisiera asegurarme de que el enfoque va a ser después el adecuado para una aplicación que pueda aumentar mucho de tamaño con facilidad.

.

Cita:

Empezado por Sick boy (Mensaje 331272)
PD: Cuando digo que algo esta bien o esta mal, es mi opinion, cada uno despues hace lo que le parece mejor.

totalmente de acuerdo, el intercambio de impresiones siempre es positivo a todos los niveles, gracias

RolphyReyes 17-12-2008 15:48:18

Cita:

Empezado por levanteelx (Mensaje 331245)
además los componentes fibplus no tienen componentes dbware en los que se pueden limitar el número de registros que digamos se puedan 'cargar' por cada petición de refresco del cliente por ejemplo

No es necesario que los componentes DataSet tengan esta opción solo debes de limitarlos en tu sentencia SELECT . Para FireBird tienes las sentencias First y Rows.

Debes de saber además que los FIBPlus tienen los siguientes procedimientos:
  • Refresh: Que ejecuta la sentencia que tengas definidas en la sección Refresh del componente TpFIBDataSet.
  • FullRefresh: Este reabre el DataSet, esconde eventos inncesarios y trata de localizar el registro activo.
Te exhorto a que te documentes más sobre estos maravillosos componentes; en mis proyectos personales los utilizo además de que estoy trabajando en la creación de Plantillas para realizar todo el proceso de Altas, Bajas, Modificación y demás.

Galahad 17-12-2008 16:10:55

gracias por contestar

Cita:

Empezado por RolphyReyes (Mensaje 331287)
No es necesario que los componentes DataSet tengan esta opción solo debes de limitarlos en tu sentencia SELECT . Para FireBird tienes las sentencias First y Rows.

ok, con esto resuelto la carga inicial de registros, para muchas tablas pequeñas no es necesario limitar la información, pero pienso que para otras tablas más grandes, como clientes y/o artículos, si que es necesario filtrar la cantidad de registros que aparecen en los grids, una táctica de trabajo seria la de cambiar los botones de siguiente,anterior, por otros donde por ejemplo el usuario seleccionara, 'siguientes 20 registros','anteriores ..etc ...', o mejor aun , en casos de documentos (albaranes,facturas,pedidos), se me ocurre que lo ideal seria crear botones para por ejemplo: 'dia anterior','mes anterior' que sustituyan a los de siguiente/anterior registro.

tengo entendido que no se puede utilizar un select del tipo
select last 20 from .....
para recuperar los últimos 20 registros,,según el índice activo..¿ es correcto ?
Cita:

Empezado por RolphyReyes (Mensaje 331287)
Debes de saber además que los FIBPlus tienen los siguientes procedimientos:
  • Refresh: Que ejecuta la sentencia que tengas definidas en la sección Refresh del componente TpFIBDataSet.
  • FullRefresh: Este reabre el DataSet, esconde eventos inncesarios y trata de localizar el registro activo.
Te exhorto a que te documentes más sobre estos maravillosos componentes; en mis proyectos personales los utilizo además de que estoy trabajando en la creación de Plantillas para realizar todo el proceso de Altas, Bajas, Modificación y demás.

gracias , buscaré más información sobre estos componentes, mucha suerte con la elaboración de estas plantillas

RolphyReyes 17-12-2008 16:26:47

Cita:

Empezado por levanteelx (Mensaje 331295)
g
tengo entendido que no se puede utilizar un select del tipo
select last 20 from .....
para recuperar los últimos 20 registros,,según el índice activo..¿ es correcto ?

Para esta parte debes de agregar en el ORDER BY la sentencia DESC del campo que tenga un indice de forma descendente.

Por ejemplo el campo fecha lo crearía con dos indices uno ascendente y el otro descendente entonces el query quedaría así:
Código SQL [-]
SELECT FIRST 20 *
FROM TABLA
ORDER BY FECHA DESC

O

Código SQL [-]
SELECT *
FROM TABLA
ORDER BY FECHA DESC
ROWS 20

Galahad 18-12-2008 16:37:46

fibplus consulta sobre uso de 2 transacciones simultáneas
 
me ha servido de mucha ayuda

Cita:

Empezado por RolphyReyes (Mensaje 331275)
Saludos.

Por lo que veo te estas complicando con el uso de los FIBPlus, ellos son hasta ahora los únicos componentes que utilizan el concepto de dos transacciones (Read/Write) lo que los hacen potentes para desarrollo Cliente/Servidor.

Te recomiendo visitar artículos y leer sobre las transacciones con FIBPlus.

Gracias, he leido y estoy haciendo pruebas con el uso de las 2 transacciones , tal y como dijistes, en principio está todo bien, tengo que hacer mas pruebas, pero todo parece funcionar bien. Bueno, el único tema es que tengo que hacer un dataset.fullrefresh después del afterpost para que me posicione bien los registros en un grid, pero bueno,, funciona..
El tema es que , leyendo los artículos que me indicaste en la web de los fibplus, me encuentro esto:

[code] Los tfibdataset de los fibplus tienen la posibilidad de asignar 2 transacciones, de esa manera , se puede configurar una transacción larga 'de solo lectura'


Código:

TpFIBDataSet can work with two separate transactions. SelectSQL can work in the context of one transaction and all modifying queries are executed in the context of the other transaction. This helps to avoid transaction conflicts in multi-user environment. But transaction settings greatly depend on your business model and application architecture. For example, if you use separate transactions and the AutoCommit mode you can not always use master-detail links, etc.
estoy utilizando formularios de tipo master-detail, y tanto para el master como para el detail he configurado las mismas 2 transacciones, una de lectura y otra de escritura. ¿ es esto correcto ?.
He estado intentando encontrar el motivo por que indica que si se utilizan 2 transacciones no se pueden utilizar las master-detail links,, aparentemente me funciona bien, aunque el detail lo configuro 'a mano' no utilizo la propiedad 'datasource' del link del detail.

RolphyReyes 18-12-2008 21:10:34

Saludos.

En la misma pagina que te sugerí tienen artículos sobre Master/Detail con FibPlus además tienen publicado ejemplos de todas sus funcionalidades ahí busca sobre el tema.


La franja horaria es GMT +2. Ahora son las 06:46:45.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi