Ir al contenido


Foto

Saber si otra tabla esta en edit o insert


  • Por favor identifícate para responder
11 respuestas en este tema

#1 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 715 mensajes
  • LocationEspaña

Escrito 22 agosto 2014 - 12:45

Hola compañeros, las cuestiones son las siguiente:

1º)Existe alguna manera de saber si antes de hacer un commitretaining, saber si tenemos otra tabla en edición o inserción, aparte de la que estemos en ese momento

2º)Si cancelo, un trabajo, que este no se grabe pero los que pueda hacer por medio si

Pienso en que puedo usar una variable general boleana, cuando exista una tabla en edición ponerla en true y otra variable general integer con el número de tablas en insert/append o edit y sólo hacer un commitretaining si la última variable es 0, pero me crea la duda y si una de las tablas la he cancelado.

Como siempre gracias por vuestra ayuda.
  • 0

#2 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.092 mensajes
  • LocationRepública Dominicana

Escrito 22 agosto 2014 - 05:59

Saludos.

Si entendí correctamente, me parece que estas confundiendo lo que implica las transacciones en Firebird.

Cuando comienzas una transacción de manera explicita todos los cambios (Insert, Update, Delete) realizados a una o muchas tablas dentro del contexto de la transacción al momento de realizar un CommitRetaining o Commit se almacenan de manera definitiva en la base de datos, siempre y cuando no exista un error. Dicho esto, eso implica que si el mismo usuario tiene la posibilidad de estar modificando otra tabla que no esta dentro del contexto de la transacción no se vera afectado o si es otro usuario desde otra estación de trabajo.

Si tienes más dudas, pues plantealas.

Algunos enlaces:
Enlace1
Enlace2
Enlace3
  • 0

#3 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 715 mensajes
  • LocationEspaña

Escrito 22 agosto 2014 - 08:04

Gracias Rolphi, me extiendo un poco más mi duda se presenta en el siguiente caso.

Si estamos en la inserción de una nueva factura, pero uno de los artículos no esta dado de alto, si lo creo, teniendo aún la tabla factura y factura detalle, en edición o inserción, al crear el nuevo artículo y hacer un CommitRetaing, no afecta al estado de las tablas Factura y factura detalle?

Es lo que me deja dudando y me tiene inquieto.


De todas maneras mirare los enlaces por tí facilitados.

Muchas gracias.
  • 0

#4 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 22 agosto 2014 - 09:02

Gracias Rolphi, me extiendo un poco más mi duda se presenta en el siguiente caso.

Si estamos en la inserción de una nueva factura, pero uno de los artículos no esta dado de alto, si lo creo, teniendo aún la tabla factura y factura detalle, en edición o inserción, al crear el nuevo artículo y hacer un CommitRetaing, no afecta al estado de las tablas Factura y factura detalle?

Es lo que me deja dudando y me tiene inquieto.


De todas maneras mirare los enlaces por tí facilitados.

Muchas gracias.

Eso dependerá del nivel de aislamiento que se le haya configurado a la transacción.
Una transacción puede llevar a ver los cambios de otra dependiendo de de dicha configuración.

En una transacción se puede ver todo lo que hace en ella misma. Por lo que si haces todo lo que comentas en una misma transacción no debiera de haber problema.

Saludos,
  • 0

#5 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 22 agosto 2014 - 09:37


Existe alguna manera de saber si antes de hacer un commitretaining, saber si tenemos otra tabla en edición o inserción, aparte de la que estemos en ese momento


Si cuando dices  "tabla" te refieres a un Dataset de Delphi, entonces si se puede, así:



delphi
  1. if TuDataset.State = dsInsert then // presgunta si está  en inserción
  2.   //hacer algo



Ahora bién, si necesitas  indagar acerca de más estados de un Dataset, los posibles estados son los siguientes:



delphi
  1. TDataSetState = (dsInactive, dsBrowse, dsEdit, dsInsert, dsSetKey,
  2.     dsCalcFields, dsFilter, dsNewValue, dsOldValue, dsCurValue, dsBlockRead,
  3.     dsInternalCalc, dsOpening);



Saludos.
  • 0

#6 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 832 mensajes
  • LocationMisiones, Argentina

Escrito 22 agosto 2014 - 11:41

Tal como cita Wilson, puedes averiguar el estado de cualquier tabla incluso que estén en otra base de datos o utilicen otra transacción, ya que se trata de variables en la memoria del programa y no de el estado real de las tables en sí.
Por otra parte hay dos cosas que no tienen que ver con la pregunta pero si con la manera en que encaras el asunto:
- Te recomiendo que no permitas hacer el alta de un artículo al momento de la facturación, pues son dos cosas completamente diferentes que hacen que un comercio sea desordenado.
- Si por alguna razón debieras hacer el alta o alguna modificación en la tabla de artículos, te recomiendo una técnica sencilla: Creas otra transacción, abres la tabla de los artículos usando otro DataSet (otro objeto de Delphi a la misma tabla de la DB), Haces todos los cambios que se necesiten aceptas la transacción y listo. Te recomiendo para eso el nivel de aislamiento ReadCommited.

Si llegaras a cambiar la transacción del mismo DataSet que estás utilizando perderás los datos del contexto (que se pierden en un commit o rollback y se retienen en un commitretaining o un rollbackretaining) por lo que deberías almacenar en alguna variable la posición en la que se encuentra, el estado , etc. por lo que es recomendable usar otro DataSet como expresé antes.

Saludos.

  • 0

#7 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 715 mensajes
  • LocationEspaña

Escrito 22 agosto 2014 - 01:45

Tal como cita Wilson, puedes averiguar el estado de cualquier tabla incluso que estén en otra base de datos o utilicen otra transacción, ya que se trata de variables en la memoria del programa y no de el estado real de las tables en sí.
Por otra parte hay dos cosas que no tienen que ver con la pregunta pero si con la manera en que encaras el asunto:
- Te recomiendo que no permitas hacer el alta de un artículo al momento de la facturación, pues son dos cosas completamente diferentes que hacen que un comercio sea desordenado.
- Si por alguna razón debieras hacer el alta o alguna modificación en la tabla de artículos, te recomiendo una técnica sencilla: Creas otra transacción, abres la tabla de los artículos usando otro DataSet (otro objeto de Delphi a la misma tabla de la DB), Haces todos los cambios que se necesiten aceptas la transacción y listo. Te recomiendo para eso el nivel de aislamiento ReadCommited.

Si llegaras a cambiar la transacción del mismo DataSet que estás utilizando perderás los datos del contexto (que se pierden en un commit o rollback y se retienen en un commitretaining o un rollbackretaining) por lo que deberías almacenar en alguna variable la posición en la que se encuentra, el estado , etc. por lo que es recomendable usar otro DataSet como expresé antes.

Saludos.



Siempre usos un data module con todas las tablas y desde cada modulo un datadorce que llamo dsPrincipal, por lo que al crear un nuevo articulo, lo crea con el datsorce dsprincipal, del módulo artículos y no desde el de facturas.

De todas maneras si me pones un ejemplo practico, te lo agradecería, algo muy simple, aunque creo haberte entendido y por lo que he leído de las respuestas creo que lo estoy haciendo bien.

Lo único que me queda aun en duda, aún es como saber si la base de datos y no una tabla determinada tiene transacciones pendientes.

Gracias a todos.
  • 0

#8 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 832 mensajes
  • LocationMisiones, Argentina

Escrito 22 agosto 2014 - 02:54

Con la función InTransaction puedes averiguar si una transacción está activa. Pero esta es parte de la transacción y no de la base de datos, ya que una DB puede tener activa más de una transacción.

Acerca del caso de usar dos transacciones, no puedo poner un ejemplo, pero amplío aquello del mensaje anterior.

TR1 es la transacción en la cual se da la generacón de la factura.
TR2 es la transacción en la que se da el proceso de modificación dela tabla de artículos.
Un DataSet solo puede tener una transacción activa y una base de datos asignada en un momento. Si bien, es posible cambiar esto, no es muy útil en la mayoría de las veces. Entonces utilizamos dos Datasets para la misma tabla, uno que está asociado a la transacción TR1 y otro a la transacción TR2.
DSET1 es el dataset para la tabla artículos dentro de la transacción de la factura
DSET2 es el dataset para la tabla artículos dentro de la transacción del mantenimiento de la misma.
Mientras que estemos trabajando sobre el DSET1 y lo utilicemos solo para leer la información de los artículos lo haremos dentro de la transacción TR1. Pero cuando querramos modificar los datos de la tabla, utilizaremos el DSET2 que se encuentra dentro de la transacción TR2. Se supone que lo haremos en una ventana diferente.
La transacción TR2 debería cerrarse antes de volver a modificar datos correspondientes a la transacción TR1, al hacer un COMMIT en TR2, se cerrarán todas las tablas que intervienen (aquella asociada a DSET2 y quizá otras). Al fijar el nivel de aislamiento READ_COMMITED lo que le dices es que una vez realizado el COMMIT, otra transacción podrá ver el resultado de dicha transacción (terminada con COMMIT). Para cambiar el nivel de aislamiento de las transacciones, puedes hacerlo en forma visual haciendo doble clic sobre el icono de la transacción y cambiar en el diálogo (hay botones de radio con las opciones).

El tema es que los cambios que hagas en la tabla de artículos podrán verse en la transacción de la factura o sea TR1 luego de cerrarse la transacción de la modificación de la tabla de artículos o sea TR2.

Pero, insisto, que más allá que esto parezca práctico para el operador, será un problema para el sistema, pues:
1. El cliente espera... y el operador se dedica a crear un artículo inexistente.
2. Si el proceso de alta es rápido, puede ser por falta de datos, lo que significa tener que conocer cuál artículo fue dado de alta en forma incompleta para salir del paso.
3. En un ambiente con más de una PC no podrías solucionar el problema de la codificación (al menos no de manera sencilla).


Si encuentro un ejemplo "saludable" lo pongo en este hilo, pero lo dudo.
Saludos.


  • 0

#9 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 715 mensajes
  • LocationEspaña

Escrito 23 agosto 2014 - 01:59

Hola Cram, muchas gracias por tu respuesta, te pongo unas imágenes de los módulos que en este caso afectan y una breve descripción, así podrías decirme si es correcto o no el método usado.

Primero el DataModule

Imagen Enviada

Con un detalle de como esta configurado el Ibtrasinction

El módulo auxiliar de Facturas desde donde cargo los datos o los creo

[img width=800 height=303]http://nsae01.casimages.net/img/2014/08/23/140823094834971051.jpg[/img]

En el puede ver 3 puntos

1º) Es el botón desde el que llamo al siguiente módulo
2º) Es el Datasource que conecta en este caso  con Facturadetalle
3º) Es el DataSource que conecta con el Datamodule  con el ibdataset(Productos, sólo como lectura en este caso)

El módulo de productos que es llamado

[img width=800 height=447]http://nsae01.casimages.net/img/2014/08/23/140823095347940442.jpg[/img]

Como puedes ver tiene un único punto

1º) Es el DataSource que conecta con el Datamodule  con el ibdataset(Productos), desde este es de donde creo , modifico o elimino los productos.

El programa esta en mono puesto, hasta la fecha no me e atrevido con las redes ni he conseguido clientes para ellos, aunque hice algún pinito en mi anterior empresa.


Pensaba que las transacciones afectaban a todos los datos grabados en la tabla en general y no  eran coodependientes del dataset de cada tabla controlados por el datasource supongo.


  • 0

#10 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 832 mensajes
  • LocationMisiones, Argentina

Escrito 23 agosto 2014 - 12:10

En el datamodule, deberías crear otra transacción, por ejemplo IBTransactionABM (por darle un nombre).
Además en el mismo Datamodule, deberías crear un Dataset que conecte con la misma tabla de productos, o sea la misma tabla que es utilizada en el DataSet "apuntado" por el DataSource dsPrincipal (Que no alcanzo a entender cual es y no viene al caso, pues los sabes y eso cuenta). Este segundo Dataset deberá tener como Base de datos la misma que el otro (que ya tienes) y como transacción a IBTransactionABM (ReadCommited).
Entonces, cuando necesites agregar, o modificar algún artículo (o producto, como sea), deberías abrir una ventana que hace ese trabajo utilizando el segundo dataset creado (con otro datasource, obviamente) y dentro de la transacción IBTransactionABM. Cuando abres la ventana de alta o modificación, estarás en otra transacción [y no importa que esté abierta una primera], una vez que hagas las modificaciones y aceptes los cambios y termines la transacción (COMMIT), y vuelvas a la ventana de facturación, el artículo nuevo o modificado deberá ser visible. Existe una función llamada Refresh que a veces es necesaria, dependiendo de la manera en que esté configurado el dataset.

Espero que entiendas con esto, pues veo que está todo en el Módulo de datos, tal como Yo tengo mis cosas y los ejemplos de esta forma se hacen complicados. Hay quienes lo hacen todo mediante código y además de tener el control absoluto desde código se pueden tomar ejemplos.

Saludos
  • 0

#11 Desart

Desart

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 715 mensajes
  • LocationEspaña

Escrito 24 agosto 2014 - 04:43

Cram, una última pregunta, ¿Sólo necesito un IBTransaction para todas las tablas, o necesito más de uno?
Actualmente uso uno y a este le hago todas las operaciones
  • 0

#12 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 24 agosto 2014 - 07:56

Cram, una última pregunta, ¿Sólo necesito un IBTransaction para todas las tablas, o necesito más de uno?
Actualmente uso uno y a este le hago todas las operaciones

La sugerencia de Cram apunta a que dispongas de varios IBTransaction, y que cada uno controle su contexto.
Todo depende de a como uno diseñe la aplicación.
Se puede llegar a tener un único IBTransaction y continuamente estar trabajando con este, aplicando debidamente a tiempo los COMMIT correspondiente. Cuando es mono puesto la cosa es sencilla, siempre se va estar seguro. La cosa es cuando se pasa a cliente/servidor; que también se puede si uno se es prolijo y si a dicho IBTransaction se le va configurando adecuadamente el nivel de aislamiento y realizando los COMMIT y/o ROLLBACK a tiempo.
Pero si no se controla esto es posible que deje abierta transacciones que nunca terminen, o que no sea capaz de leer datos confirmados de otros clientes.

Pero también puede ser muy sano, y bastante prolijo, si se disponen de varios. De modo que a cada uno se le de cierto uso/fin de acuerdo al nivel de aislamiento y funcionalidades esperadas.
Por ejemplo, para los informes es bueno que tengan su propia transacción con el nivel READ COMMITED.
Para casos como el que tu describes también puede servir el tener una 2da transacción adicional, extra auxiliar, para usar en operaciones de tipo "búsquedas rápidas" o "altas al vuelo" mientras se está en stand by con la 1ra. Lo importante es que cuando se confirme o se cancele la 2da transacción, la 1ra pueda enterarse de los cambios.

Ahora bien, tampoco es sano que cada tabla tenga su propio IBTransaction. No hay que llegar a ese extremo. Una buena práctica puede ser tener un Transaction por cada módulo/submódulo de la aplicación. Por ejemplo uno para lo que es Facturación, otro para Proveedores, etc. Luego uno o dos extras auxiliares.

Lo importante detrás del concepto de transacción es que se entienda su objetivo: Dejar SIEMPRE a la base de datos en un estado consistente. Las operaciones se realizan todas o nada. No hay término medio. Si dentro de una transacción se realizan 20 UPDATES, 5 DELETE, 1 SELECT y 3 INSERT todo debe hacerse bien, si se cancela todo lo hecho vuelve atrás, y es como si no se hubiera cambiado nunca nada.
Cuando se tienen muchas transacciones operando es fundamental controlar adecuadamente que cada una, para lo que se espera que haga, sepa poder ver los cambios que posiblemente una tercera aplique a posibles datos de interés con lo que espera trabajar. De allí surge el nivel de aislamiento.

Recomiendo leer los enlaces que te ha dado Rolphy. Yo por mi parte RECOMIENDO, y casi me animo a decir que debiera ser lectura obligada, leer el paper del gran Kenobi, un antiguo miembro de la comunidad de Delphi: Transacciones en Interbase y Firebird. Lo puedes descargar desde la sección Descargas.
Este documento te ayudará enormemente a comprender el mundo de las transacciones.

Saludos,
  • 0




IP.Board spam blocked by CleanTalk.