PDA

Ver la Versión Completa : Ayuda con componente transaction


boreg
26-11-2007, 20:12:08
Saludos a todos, estoy usando lazarus y esta vez mas que un problema es una duda que quiero aclarar y es que me paso lo siguiente.

Estoy usando los componentes FIBL, tengo un componente de Base de Datos en un formulario (FORM1), y en otro Formulario(FORM2), tengo un transaction, un query y un dataset estos dos ultimos ligados al transaction.
Los componentes del FORM2 los ligue a la base de datos por medio de codigo en el evento OnCreate del mismo FORM2.

Código Delphi [-] (http://www.clubdelphi.com/foros/#)
Transaction.DefaultDatabase:=Form1.Database;
Query1.DefaultDatabase:=Form1.Database;
Dataset1.DefaultDatabase:=Form1.Database;
//activo el Transaction
Transaction.Active:=True;




pues resulta que despues de hacer un commit en el transaction, este pasa a estado inactivo, lo cual compruebo al ejecutar alguna consulta con el query y me marca que el transaction esta inactivo "Transaction is not active", esto lo solucione activandolo nuevamente con codigo despues de cada commit

Código Delphi [-] (http://www.clubdelphi.com/foros/#)
Transaction.Commit;
Transaction.Active:=True;




pero no creo que deba ser asi, ya que cuando lo activo desde el modo diseño no hay que hacer lo mismo despues de cada commit. Y mi duda seria:

¿Hay alguna forma de evitar tener que reactivar el transaction despues de cada commit?

En el caso de los datasets creo que no hay problema ya que tienen una propiedad llamada AutoStartTransaction que por lo que entiendo activa el transaction automaticamente y funciona bien pero el problema es con los Query ya que estos no tienen esa propiedad.
Espero alguien tenga una solucion o comentario que me ilustre un poco mas con respecto a estos componentes. De antemano MUCHAS GRACIAS!!!.

Chris
26-11-2007, 20:31:39
Más bien, ese es un problema con la configuración de la transacción. Cuando me inicie en firebird por medio de delphi, me daba el mismo problema, pero lo solicione con esta configuación. En la propiedad params del componente de la transación ingresa:

read_committed
rec_version
nowait

No sé si será la mejor configuración, pero esta es la que me funciona.

Saludos.

boreg
26-11-2007, 20:43:30
Saludos D&W, muchas gracias por tu respuesta, ya intente lo que mencionas pero sigo con el mismo error "Transaction is not active", supongo que te referias en mi caso a la propiedad TRParams, ya que es ahi donde puse el texto que escribiste y quede igual, alguna otra sugerencia?

Chris
26-11-2007, 23:59:13
Sinceramente, no conozco los componentes, seguramente alguien del club pueda ayudarte con ellos, pero por el momento porque no intentas buscar alguna propiedad que esté releacionada a este comportamiento, como por ejemplo CloseAfterCommit o DeactiveAfter... algo por el estilo. Estas cosas aveces son como una caja fuerte, en donde tienes que hayar la combinación. No busques solo en la transacción porque también el pegón puede estar en el componente de conexión a la BD.

Asegurate también, que la conección entre el componente de BD y transación sea reciproca.

Saludos.

boreg
27-11-2007, 00:54:32
Pues muchas gracias por interesarte D&W seguire buscando donde esta la diferencia como indicas, y espero encontrarla, ya de paso te comento que esas propiedades que me mencionaste antes, parece que se ponen automaticamente sin escribirlas en diseño o en codigo. !!Mil gracias!!

duilioisola
27-11-2007, 11:37:52
Yo trabajo con los FIB pero en delphi.
Hay dos formas de hacer commit

Transaction.Commit
Transaction.CommitRetaining

La primera hace el commit y cierra la transacción. La segunda mantiene la trasnacción abierta.

Lo malo de sobreutilizar el CommitRetaining es que al no cerrarse nunca, se van acumulando capas de transacciones hasta que se hace el commit final.

Imagínate dos usuarios y sus transacciones:

USU1-StartTransaction
USU2-StartTransaction
USU1-hace cosas
USU1-CommitRetaining
USU2-hace cosas
USU2.CommitRetaining

En este momento la base de datos tiene registado todo lo que han hecho los dos usuarios, sin poder liberar ninguna transaccion definitivamente. A lo largo del día, esto puede generar una degradación en la eficiencia de la base.

Cuando finalmente USU1 cierra:
USU1.Commit
La base de datos puede hacer una limpieza de trasacciones hasta la próxima que sigue abierta (la de USU2)

Cuando USU2 hace su Commit:
USU2.Commit

Puede limpiar (hacer un commit final) la lista de transacciones de USU2 y a las de USU1 que estén sobre ella.

Espero no haberte liado mucho.

duilioisola
27-11-2007, 11:48:04
Otro consejo o regla que deberías seguir:

Las transacciones deben ser lo más cortas posibles.

Por lo tanto,
- Cada form debería tener una transaccion independiente.
- Cada listado debería tirar de un query con su propia transaccion.
- Si necesitas buscar algún dato deberías hacerlo abriendo y cerrando la transacción inmediatamente.

Por lo tanto:
- Deberías tener un DataModule principal con el componente de base de datos
- Cada Form debería tener su DataModule con una transaccion unida a la base de datos del DataModule principal
- Para consultas aisladas yo hago lo siquiente:

function Form1.DameCantidadDato: Integer;
var
q: TFibQuery;
begin
q := TFibQuery.Create(Self);
try
q.Database := DMMain.Database;
q.Transaction := TFibTransaction.Create(Self); {Crea transaccion}
q.Transaction.DefaultDatabase := DMMain.Database;
q.Transaction.StartTransaction; {Empieza transaccion}
q.SQL.Text := 'SELECT COUNT(*) FROM TABLA';
q.ExecQuery;
Result := q.FieldByName['COUNT'].AsInteger;
finally
q.Transaction.Free; {Termina transaccion}
q.Free;
end;
end;

boreg
27-11-2007, 17:40:36
Gracias Duilioisola por tu respuesta es precisamente lo que estoy haciedo,cada formulario tiene su transaction y sus componentes, pero mas que el diseño de mi aplicacion mi duda es sobre el porque tener que reactivar el transaction despues de cada commit al activarlo por codigo



Transaction.Active:=True; //Transaction inactivo desde el diseño
TRansaction.Commit;
Transaction.Active:=True; //Linea que intento no escribir
Dataset.Active:=True;
Query.ExecSQL; //En el caso de no reactivar el transaction, el query no se ejecutara.

y cuando se queda activo desde el modo diseño no hay que activarlo nuevamente despues de cada commit o rollback.




Transaction.Commit; //Transaction activado desde el diseñoDataset.Active:=True;
Query.ExecSQL; //Aqui no me marca problemas con el query ya que el transaction no se desactiva despues de hacer commit


Como mencionaba antes en el caso de los datasets quizs no haya tanto problema ya que con la propiedad AutoStartTransaction no es necesario Activar por codigo los transactions, pero con los Query's sí es necesario ya que carecen de esta propiedad.Seguire buscando la solucion a menos de que alguien me diga que es nocivo para la aplicacion o la base de datos el tener permanentemente activos los transactions.


Como sea muchas gracias por la ayuda, y quiero decirles que me es grato que me hayan contestado ya que en intentos pasados no tuve la misma suerte de esta vez, quizas no expuse bien mis dudas quien sabe.

boreg
27-11-2007, 19:27:33
Hola de nuevo, ya nada mas paso para decir que mi idea de usar el commit, parece que estaba erronea, segun yo lo usaba para actualizar mis datos para que cuando hiciera alguna consulta estos fueran los mas actuales, lo que es igual que usar el StartTransaction, como me indicaste Duiliisola, pero con la diferencia de que esta ultima activa el transaction. Ahora todo esta un poco mas claro.

Pues creo que aun me falta mucho por aprender asi que quizas los estaré molestando un rato por aca, y quien sabe en alguna ocasion quizas pueda colaborar con algo. Saludos!!!!!