![]() |
Asesoramiento: ¿Tablas temporales, datos en memoria...?
Hola a todos y gracias por el interés. He intentado simplificar los detalles e ir al grano, pero si hay dudas profundizo en el tema.
Tengo que revisar una aplicación que está dando problemas de grabación ya que se producen inconsistencias en la BD. Utilizo Delphi7 y Oracle9i. Es un sistema para dar de alta solicitudes de clientes de forma telefónica, y se utilizan 3 formularios para los diferentes pasos, y ese es el problema, que cada formulario graba lo suyo sin llevar un control de coherencia y al final te puedes encontrar con líneas de presupuesto sin cabecera si se produce algún fallo durante el proceso o se cancela. Consta de 3 tablas: * Solicitud: cabecera que engloba una llamada concreta de un cliente que suele traducirse en varios presupuestos relacionados. * Det_Solicitud: cabecera del presupuesto (para una única empresa). * Det_Ppto: líneas del presupuesto, servicios concretos de la empresa. Mi intención era crear 3 tablas temporales (o algo así) para almacenar los datos y sólo grabar al finalizar totalmente el proceso. Me gustaría: * Algo sencillo de incorporar, ya que tengo que revisar y sustituir un montón de código. * Preferiría no tocar físicamente la BD ya que es una aplicación cliente/servidor que se mantiene por un sistema de espejos que se replican desde los servidores de las delegaciones al servidor central... un lío tremendo. Además no soy el administrador de la BD y hay que solicitar los cambios por escrito y los tiene que firmar el jefe de proyecto... otro lío. * Nunca serán demasiados datos, lo normal son unos 10 registros relacionados contando las 3 tablas. * Algunos de los datos son consultados durante el proceso y deberán ser accesibles mediante grid o edit. Estas consultas SQL ya existen y si se pudiesen mantener sería perfecto. * Si es en memoria mejor, así se borra todo cuando cierre los formularios. ¿Qué debo utilizar? ¿Cual es el mejor modo de mantener y consultar la información hasta el momento de la grabación? |
¿Qué para esto ne te sirven las transacciones? Si algo falla se cancela la transacción y con ello todos los cambios que se hayan hecho.
// Saludos |
Cita:
Estoy hablando de un proceso que puede tardar minutos en completarse, creo que eso va en contra del concepto de transacción... O por lo menos a mí no me acaba de convencer tener una transacción abierta durante tanto tiempo. |
Hola kuan-yiu!
Con respecto al tema de no tener tanto tiempo abierta una transacción, leí hace poco una solución propuesta por Lepe en este hilo que se refiere a los ClientsDataset con cacheUpdates (consigues el efecto que una tabla temporal). Te dejo un enlace con un ejemplo: ClientDataSet y DataSetProvider en aplicaciones cliente/servidor Saludos |
Cita:
(Pero voy a tener que reescribir la mitad de la aplicación :( porque el que lo hizo ni usaba DataModule ni UpdateSQL ni nada de nada.) |
Vamos a ver, que no soy experto en el tema así que más es pregunta que respuesta. ¿Exactamente, en este caso, cuál sería el problema de dejar una transacción abierta? No estamos hablando de dejar bloqueos de tablas activos. Dependiendo, según entiendo, del nivel de aislamiento de la transacción, los otros clientes pueden continuar su trabajo. Cualquier cosa que haya que deshacer con la transacción también ha de deshacerse con el uso de tablas temporales. No digo que no convenga usar ClientDataSets, y posiblemente sea lo más adecuado, pero tampoco me queda claro el porqué afecta una transacción abierta. Pero como dije, es más pregunta que respuesta.
// Saludos |
Cita:
El problema radica, creo yo, en un mal diseño inicial de la aplicación que ahora está dando muchos fallos y tengo que remendar de algún modo (usa 6 formularios diferentes durante todo el proceso, muchos de ellos de consulta y hay decenas de lugares en los que puede cancelar el proceso a media grabación produciendo los más variados desastres). Así que lo que yo pretendo es unificar la grabación física en un único punto, al finalizar todo el proceso, para hacerla más robusta.Aunque tal vez esa tampoco sea la mejor solución. :confused: |
Cita:
|
Quizas por problemas de atomicidad... mientras esta el proceso otros pueden modificar los datos de base, lo que implica que para proteger el proceso se deberia de aislar la transaccion.
Si el proceso es de mucho tiempo, las transacciones no necesariamente es lo mejor. |
Entiendo esto, pero si el que otros usuarios hagan modificaciones durante la transacción es algo que pueda afectar en este caso, pues lo mismo sucedería con las tablas en memoria ¿no?
// Saludos |
El proceso dura mucho, demasiado, es el típico proceso:
Cita:
El problema fundamental es que tengo que insertar cosas y luego consultar esos mismos datos... me estoy volviendo loca :mad: , estoy a punto de tirarlo todo y volver a hacerlo. Estoy tentada de llenarlo todo de flags y de montones de mensajes de aviso y de mega-funciones-de-borrado-en-masa... |
Cita:
|
Cita:
RollBack y Commit, simpre los uso y nunca me han dado problemas, ahora no sé porque se deben ir grabando los datos a medida que se vaya completando el proceso, nunca he visto este tipo de aplicación :confused: |
Cita:
Pero como voy a empezar una transacción en un botón de un formulario, cambiar 7 veces de formulario para hacer otras cosas y acabarla en otro botón de otro formulario... Me parece demasiado pretender meterlo todo en la misma transacción. A ver, que parece que no me explico nada bien: Form1 : graba "Solicitud" y borra posibles líneas anteriores de "Det_Ppto". Además de otras cosas. Form2: graba "Det_Ppto", añade datos a "Solicitud" y borra posibles líneas anteriores de "Det_Solicitud". Además de otras cosas. Form3: graba "Det_Solicitud". Además de otras cosas. Form4: usado por "Form1" para seleccionar el cliente. Form5: usado por "Form1" para seleccionar la empresa. Form6: usado por "Form2" y "Form3". Form7: usado por "Form2". El problema, creo yo, radica en que las tablas han tenido que ser ampliadas porque se necesitaba almacenar una serie de datos que inicialmente no habían sido considerados y creo que se hizo mal, por eso el proceso da tantas vueltas. |
¡¡Ya lo tengo!!
He creado esta estructura de componentes: * 3 TQuery con la consulta a la tabla correspondiente. Con la propiedad "Cached Updates" a true. * 3 TDataSource para relacionar las consultas y mostrar los datos. * 3 TUpdateSQL para controlar la inserción, relacionados con las consultas a través de la propiedad "UpdateObject". He sustituido todas las inserciones en la base de datos por métodos apend en los correspondientes TQuery. Las modificaciones y borrados igual, primero un locate y después lo que corresponda. Al finalizar todo el proceso, junto con la última grabación lanzo un procedimiento que inserta todos los datos en una única transacción. Me soluciona todos los problemas: * He tardado en encontrar la solución (y he intentado varias que no han servido) pero el resultado es simple y elegante... o eso me parece. * Si no finaliza el proceso no graba nada. * Permite consultar los datos en cualquier momento del proceso. * La estructura de componentes está en un DataModule y es accesible para todos los formularios en cualquier momento. * No tengo que redefinir nada en la BD. * Me sirven los formularios tal y como están. Los cambios son mínimos. * Me ahorro un móntón de consultas y chequeos que ahora están en un único punto. |
Si utilizas oracle 9i deberias utilizar transacciones (Startransaction, commit, rollback) y ademas hay otro tema que deberias tener en cuenta. Existen savepoints (puntos de restauración) los cuales puedes definir varios (bastantes) de manera que al deshacer una transaccion podrías darle un rollback a un punto o dos o tres o....... anteriores con lo cual tu programa podía ir cerrando etapas y no mantener una transaccion abierta tanto tiempo como dices (recursos, bloqueos . . . . .). De todas formas puede ser que el fallo no venga de la transaccion, (tendrías el mismo problema con tablas temporales) sino del planteamiento de la pantalla de entrada de datos y del momento en que bloqueas tablas / recursos del sistema.
|
La franja horaria es GMT +2. Ahora son las 04:56:07. |
Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi