 |
Club Builder Foro de C++Builder en español
|
| Ver tema anterior :: Ver tema siguiente |
| Autor |
Mensaje |
gsllamas Cdt

Registrado: 26 Jun 2004Mensajes: 5Ubicación: Ensenada, B.C. Mexico
|
Publicado: Jue 08 Jul, 2004 8:17 pm Asunto: Transacciones en Interbase con IBX |
|
|
Hola,
Tengo una pregunta un poco extrana:
Programando en C++Builder con IBX tengo la siguiente situacion:
En un Form utilizo los siguientes componentes para leer productos:
Edit1
DBGrid1
DataSource1
IBQuery1
IBTransaction1
En IBQuery1->SQL asigne "SELECT * FROM PRODUCTOS WHERE codigo LIKE
:pCadena" con su respectivo parametro. Y este query se ejecute cada que
modifico el Edit1 (Evento OnChange) mostrando los productos en el DBGrid1.
Algo asi como:
IBQuery1->Close();
IBQuery1->Params->ParamByName("pCadena")->AsString = Edit1->Text;
IBQuery1->Prepare();
IBQuery1->Open();
Por otra parte en el mismo Form tengo estos componente para agregar
productos:
IBQuery2
IBTransaction2
En IBQuery2->SQL asigne ""EXECUTE PROCEDURE ADD_PRODUCTO( ... )" con sus
respectivos paremetros. Ahora, la ejecucion de IBQuery2 esta encerrada en
IBTransaction2->StarTransaction e IBTransaction2->Commit.
El hecho es que funciona correctamente, pero despues de muchos lecturas y
escrituras de nuevos productos, la aplicacion se pone muy lenta. Si cuando
se pone insoportable quiero reiniciarla me dice: "112 [mas o menos]
connections active; Are you sure you want to exit?".
Cabe mencionar que la aplicacion no me marca ninguna anomalia en una maquina
(1.1 Ghz 256 RAM) WinXP que es donde estoy programando, pero en una maquina
(233 Mhz y 32 MB RAM ) con Win98 se presenta esta situacion.
Les agradezco cualquier ayuda...
Gabriel S. Ll. |
|
| Volver arriba |
|
 |
cecito Capt

Registrado: 25 Nov 2003Mensajes: 164Ubicación: Arequipa - Perú
|
Publicado: Jue 08 Jul, 2004 10:32 pm Asunto: Re: Transacciones en Interbase con IBX |
|
|
Cada vez que ejecutas el IbQuery1 Aperturas y cierras la transaccion?
Te Recomendaria trabajar mejor con el componente TIBClientDataSet para todos los componentes que deben mostrar o editar información de una tabla( TDBEdits, TDBGrids, etc)
Los TIBQuerys usalos cuando de forma explicita deseas indicar una inserccion , actualizacion o borrado
Tambien los puedes usar para mostrar la información dentro de un reporte( asumo que usas el Quickreport) con la propiedad unidirectional a true
Para los casos de mostrar informacion en un formulario( No reporte ) usa TIbClientDatasets
conectado a un TIBtransaction con la
propiedad AutoStop = saCommit
Te recomiendo usar la siguiente configuración en el Modulo de datos
1) Un objeto TIBTransaction llamado TransDB al cual solo le conectas el TIBDataBase ( y te olvidas de el )
2) Un objeto TIBTransaction llamado Trans al cual le conectas todos tus TIBQuerys(con unidirectional = true) y TStoredProcedures existentes en este Modulo de Datos
3) Un objeto TIBTransaction(con AutoStop = saCommit) llamado TransCDS al cual le conectas todos tus TIBClientDataSets existentes en este Modulo de Datos
Si tienes varios Modulos de Datos (TDataModule) te recomiendo repetir el caso 2 y/o 3 si es que tienes TIBQuerys, TStoredProcedures o TIBClientDataSets ( colocas los mismos nombres)
ahora si quieres ejecutar un query(qr) o SoredProcedure, en procedimiento harias algo como esto
Trans->Starttransaction();
qr->Close();
try
{ qr->SQL->Text = " insert into Clientes(Nombre) values('JUAN')";
qr->ExecSQL();
}
__finally
{ Trans->Commit();
}
en el caso del TIBClientDataSet(cds) usarias
cds->Open();
- y se abrira de forma automatica la transaccion
- se cargan los datos
- se cierra la transaccion pero los datos ya los tienes en el TIBClientDataSet(cds)
Al componente se le trabaja como si fuese un componente TTable
puedes hacer por ejemplo una inserccion
cds->Append();
o un Borrado
cds->Delete();
igual se de indicar cds-ç>Post() o cds->Cancel()
para confirmar o cancelar los cambios
Si llegas hasta aqui y lo pruebas te vas llevar la sorpresa que si borras, modificas o inserta al final no se refleja en la base de datos
Para corregir esto al finalizar la operación o grupo de operaciones que haces sobre el TIBClientDataSet(cds) finalizas con esta línea
cds->ApplyUpdates(0);
y listo
cualquier duda escribeme al
VPRADOCUEVA@UNSA.EDU.PE
[/b] |
|
| Volver arriba |
|
 |
gsllamas Cdt

Registrado: 26 Jun 2004Mensajes: 5Ubicación: Ensenada, B.C. Mexico
|
Publicado: Jue 08 Jul, 2004 11:34 pm Asunto: Re: Transacciones en Interbase con IBX |
|
|
Voy a probar esta sugerencia que me das:
Pero te comento algo mientras para que me aclares algo:
Tengo varios TForms y en cada uno segun yo, agrego los componentes que ocupo con su respectivo TIBTransaction.
Es esto redundante o innecesario? O es preferible utilizar un solo TIBTransaction para todas las operaciones de lectura (por ejemplo)?
| cecito escribió: | Cada vez que ejecutas el IbQuery1 Aperturas y cierras la transaccion?
1) Un objeto TIBTransaction llamado TransDB al cual solo le conectas el TIBDataBase ( y te olvidas de el )
2) Un objeto TIBTransaction llamado Trans al cual le conectas todos tus TIBQuerys(con unidirectional = true) y TStoredProcedures existentes en este Modulo de Datos
3) Un objeto TIBTransaction(con AutoStop = saCommit) llamado TransCDS al cual le conectas todos tus TIBClientDataSets existentes en este Modulo de Datos
Si tienes varios Modulos de Datos (TDataModule) te recomiendo repetir el caso 2 y/o 3 si es que tienes TIBQuerys, TStoredProcedures o TIBClientDataSets ( colocas los mismos nombres)
[/b] |
|
|
| Volver arriba |
|
 |
cecito Capt

Registrado: 25 Nov 2003Mensajes: 164Ubicación: Arequipa - Perú
|
Publicado: Vie 09 Jul, 2004 6:54 am Asunto: |
|
|
Te recomiendo usar un TIBTransaction(Trans) para todos tu TIBQuerys pero debes seguir la siguiente estructura siempre:
Trans->Starttransaction();
//Usas tu query
Trans->Commit();
Seria preferible que encierres todo dentro de un bloque try/finally para el control de errores
Sin importar si se usa uno o muchos TIBTransactions, prefiero centralizarlos en los mó-dulo de datos( pero siempre hay excepciones), el diseño que te propongo a sido uno que la experiencia me ha enseñado( el que menos Horrores me a causado con las transaccio-nes), por que como habras podido comprobar no hay mucha información, solo uno que otro paper y sobre todo para delphi
Te sigo recomendando usar los TIBClienDasets o TClientDatSets estos te van a simpli-ficar la vida por que ellos administran de forma automática la transacción.(Recuerda ellos abren la transacción, traen todos los datos y cierran la transacción, y lo que tienes es un copia local de los datos) recuerda que para configurar estos componentes vas a su propiedad CommandText y le configuras una sentencia sql( “Select * from Tabla where Condicion”), puedes crearle parámetros, puedes crear campos calculados, campos calcu-lados internos(los cuales nos permiten crear indices basados en ellos), y las mas bonito campos Agregados(Aggegate Fields) los cuales nos pueden totalizar una columna o hallar el promedio de otra según lo indiquemos en la propiedad Expresion( ejem. Sum(Gastos) ).
Además su propiedad filter es la mas completa de todos los objetos derivados de un TDataSet.
Para solucionar tu problema olvidate del TIBQuery usa un TIBClientDataset la primera vez que lo llames en tu ventana lo abres y te traes todos, SI TODOS los datos, luego le aplicas un Filtro( ejemplo Filter=”Codigo = ‘TUER*’“ Todos los que empiecen con TUER) las siguientes llamadas solo cambias el filtro. Esto es mucho más rápido que estar consultando constantemente a la base de datos, en mis aplicaciones hago uso de esta forma de trabajo, la primera vez que se apertura le cuesta algunos segundos pero luego como son puros filtros en tu COPIA LOCAL de los datos esto es rapidísimo, lo he probado con 28 mil registros y es más que eficiente y ahora si te parece pesado traerte todo cada vez que abres la ventana este objeto nos permite guardar los datos a un fiche-ro y recuperarlos
Revisa esto
http://www.dbginc.com/tech_pprs/ibxcds.html
te va a enseñar a usar el TClienDataSet(El TIBClientDaSet es un componete que encap-sula a TClienDataSet, un TDataSetprovider y un TIBQuery )
Te recomiendo que tus ventanas no abran las tablas que usas o inicialicen la transacción usa mejor esta idea: Creas un Procedimiento en el modulo de datos el cual debe inter-namente abrir transacciones ,tablas, crear la ventana y al final cerrar tablas, transaccio-nes,, ejemplo:
void Tdatamodule::Ventas()
{ TVentana p = new TVentana(NULL);
cdsVentas->Open();//ClientDataset para Ventas
try
{ if( p->ShowModal()==mrOK )
{ cdsVentas->Post();
cdsVentas->ApplyUpdates(0);
}
}
__finally
{ cdsVentas->Close();
delete p;
}
}
La ventana ventas tiene dos botones:
Botón Grabar con su ModalResul = mrOK
Botón Cancelar con su ModalResul = mrCancel
He creado una clase para encapsular el manejo del SQL ahi te lo envió, podría servirte:
Util.h
#include <IBCustomDataSet.hpp>
#include <IBQuery.hpp>
#include <IBStoredProc.hpp>
#include <Db.hpp>
#include <DBClient.hpp>
AnsiString F( char * Texto, ...);
class TSQL
{
TIBQuery * qr;
AnsiString tmp;
bool EliminarQuery;
bool EliminarTrans;
bool AperturoTransaccion;
TIBTransaction *trn;
// static TIBTransaction * Trans
public:
class TFinSQL{};
TSQL( TIBQuery * qr );
TSQL( TIBTransaction * Trans = NULL );
TSQL( TSQL & SQL );
~TSQL();
static TIBDatabase * Database;
// static bool TransaccionCompartida;
void __fastcall operator=(AnsiString Texto);
inline TField* operator()(AnsiString cc){ return qr->FieldByName(cc); }
inline TIBQuery * operator->() { return qr; }
inline operator TIBQuery * (){ return qr; }
inline void Transaccion(){ trn->StartTransaction();}
inline void Commit(){ trn->Commit();}
inline void Rollback(){ trn->Rollback();}
inline bool TransActiva(){ trn->InTransaction;}
TSQL & operator<<(const char * t);
TSQL & operator<<(const AnsiString &t);
TSQL & operator<<(const int & t);
TSQL & operator<<(const double & t);
TSQL & operator<<(const TDate & t);
void TSQL::operator<<(TFinSQL t);
};
TIBDatabase * TSQL::Database = NULL;
const TSQL::TFinSQL fs;
//-----------------------------------------------------------------
Util.cpp
#include <stdio.h>
#include " uUtil.h"
AnsiString F( char * Texto, ...)
{ char buf[2048];
va_list args;
va_start(args,Texto);
vsprintf(buf,Texto, args);
va_end(args);
return AnsiString(buf);
}
//---------------------------------------------------------------------------
TSQL::TSQL( TIBQuery * qr )
{ this->qr = qr;
qr->Close();
trn = qr->Transaction;
AperturoTransaccion = false;
EliminarQuery = false;
EliminarTrans = false;
}
//---------------------------------------------------------------------------
TSQL::TSQL( TIBTransaction * Trans )
{
if( Trans == NULL )
{ EliminarTrans = true;
trn = new TIBTransaction(NULL);
trn->DefaultDatabase = Database;
}
else
{ EliminarTrans = false;
trn = Trans;
}
qr = new TIBQuery(NULL);
qr->Transaction = trn;
EliminarQuery = true;
AperturoTransaccion = false;
}
//---------------------------------------------------------------------------
TSQL::TSQL( TSQL & SQL )
{
qr = new TIBQuery(NULL);
qr->Transaction = SQL.qr->Transaction;
trn = qr->Transaction;
EliminarQuery = true;
AperturoTransaccion = false;
EliminarTrans = false;
}
//---------------------------------------------------------------------------
TSQL::~TSQL()
{ qr->Close();
if( AperturoTransaccion )
if( trn->InTransaction )
trn->Commit();
if( EliminarQuery )
delete qr;
if( EliminarTrans )
delete trn;
}
//---------------------------------------------------------------------------
void __fastcall TSQL::operator=(AnsiString Texto)
{
AnsiString tmp = Texto.Trim().UpperCase();
if( !TransActiva() )
{ AperturoTransaccion = true;
Transaccion();
}
qr->Close();
qr->SQL->Text = tmp;
if( tmp.SubString(1,6)=="SELECT" )
qr->Open();
else
qr->ExecSQL();
}
//---------------------------------------------------------------------------
TSQL & TSQL::operator<<(const char * t)
{ tmp += t;
return *this;
}
//---------------------------------------------------------------------------
TSQL & TSQL::operator<<(const AnsiString &t)
{ tmp += t;
return *this;
}
//---------------------------------------------------------------------------
TSQL & TSQL::operator<<(const int & t)
{ tmp += IntToStr(t);
return *this;
}
//---------------------------------------------------------------------------
TSQL & TSQL::operator<<(const double & t)
{ tmp += FloatToStr(t);
return *this;
}
//---------------------------------------------------------------------------
TSQL & TSQL::operator<<(const TDate & t)
{ tmp += F("'%s'",t.FormatString("mm/dd/yyyy")) ;
return *this;
}
//---------------------------------------------------------------------------
void TSQL::operator<<(TFinSQL t)
{ *this = tmp;
tmp = "";
// ShowMessage(tmp);
// return *this;
}
//---------------------------------------------------------------------------
y para que sirve todo esto?
Podrías hacer esto:
{
TSQL a;//Crea automáticamente su transacción
a = F(“Select Nombre from tabla where Codigo = %d and Saldo = %f”, Codigo, 3.1415); //Esta sentencia al momento de asignar ya se ejecuto
ShowMessage(a(“Nombre”)->AsString);//Accedemos al campo nombre
a = “delete from Ventas”; // Al asignar se ejecuto
}//al destruirse la variable se cierra la transacción
varios deben compartir la misma transacción
{
TSQL a;//Crea automáticamente su transacción
TSQL b(a), c(a);//Se crean con la transacción de “a”
a = “Select * from tabla”;
for( a->First(); ¡a->Eof; a->Next())
{ b <<”delete from “<<a(“Tabla”)->AsString<<” where Codigo = “<<a(“Codigo”)->AsInteger<<fs;//Otra forma de escribir las sentencias, recuerdas “cout”
//fs es un truco para indicar que debe ejecutar la sentencia
c<<” insert into empleados( Nombre ) values(‘”<<a(“Nombre”)->AsString<<”’)”;
c<<fs;//recien se ejecuta
}/al destruirse la variable se cierra la transacción
Usar una transacción que ya existe
{
TSQL a(Objeto TIBTransaction);
a.Transaction();
a = F(“Select Nombre from tabla where Codigo = %d and Saldo = %f”, Codigo, 3.1415); //Esta sentencia al momento de asignar ya se ejecuto
ShowMessage(a(“Nombre”)->AsString);//Accedemos al campo nombre
a = “delete from Ventas”; // Al asignar se ejecuto
a.Commit();
}
En el modulo de datos en su evento OnCreate agrega esto:
TSQL::Database = <Tu Objeto TIBDataBase> ;
Es + o - la forma de uso espero te sirva
Si se presenta algún error o tienes alguna sugerencia escribeme a
vprado@unsa.edu.pe
( en la anterior respuesta equivoque el mail) |
|
| Volver arriba |
|
 |
Invitado
|
Publicado: Vie 09 Jul, 2004 2:10 pm Asunto: |
|
|
ya que estamos...¿es lo mismo usar
Transaction->StartTransaction() que Transaction->Active = true? |
|
| Volver arriba |
|
 |
cecito Capt

Registrado: 25 Nov 2003Mensajes: 164Ubicación: Arequipa - Perú
|
Publicado: Vie 09 Jul, 2004 3:24 pm Asunto: |
|
|
| si p |
|
| Volver arriba |
|
 |
|
|
No puedes publicar temas nuevos en este foro No puedes responder a temas en este foro No puedes editar tus mensajes en este foro No puedes borrar tus mensajes en este foro No puedes votar en las encuestas de este foro
|
© 2002–2026 Club Builder · Funciona con phpBB.
|