Recent

Author Topic: Error - Transaction of connection not set  (Read 8826 times)

valdir.marcos

  • Hero Member
  • *****
  • Posts: 1008
Error - Transaction of connection not set
« on: September 01, 2018, 04:34:25 am »
Why IBConnection component looses its information about the default SQLTransaction component after first run?

Important detail: I am using a second SQLTransaction for a SQLQuery.

I have attached a small example:
- Run the project;
- Click Button1 to open Form2;
- Click Button3 to run query. It works correctly;
- Close Form2;

- Click Button1 AGAIN to reopen Form2;
- Click Button3 to run query. It gives error "Transaction of connection not set".

EDatabaseError, SErrConnTransactionnSet, Transaction of connection not set

mangakissa

  • Hero Member
  • *****
  • Posts: 1101
Re: Error - Transaction of connection not set
« Reply #1 on: September 01, 2018, 09:01:34 am »
Wrong approach. Use Datamodule.
It looks like your sample is loosing the connection to Form1 after de caFree. Could be a bug, but I'm not sure.
The datamodule has all it needs: the connection and query at one page. THe RTTI doesn't have to search where your component are put.
Lazarus 2.06 (64b) / FPC 3.0.4 / Windows 10
stucked on Delphi 10.3.1

valdir.marcos

  • Hero Member
  • *****
  • Posts: 1008
Re: Error - Transaction of connection not set
« Reply #2 on: September 01, 2018, 11:45:35 am »
Wrong approach. Use Datamodule.
The real application uses datamodules and the problem is spread in hundreds of forms.

Quote
It looks like your sample is loosing the connection to Form1 after de caFree. Could be a bug, but I'm not sure.
I am trying to confirm the problem before open a bug report.

Quote
The datamodule has all it needs: the connection and query at one page. THe RTTI doesn't have to search where your component are put.
The real application uses datamodules to center what is general, like IBConnection; but SQLTransaction and SQLQuery belong to forms, just like in the old Delphi application that is being converted to Lazarus.

valdir.marcos

  • Hero Member
  • *****
  • Posts: 1008
Re: Error - Transaction of connection not set
« Reply #3 on: September 01, 2018, 12:13:08 pm »
The datamodule has all it needs: the connection and query at one page. THe RTTI doesn't have to search where your component are put.
I really appreciate your help, but your solution is not consistent for this case.
I can't have dozens of connections and hundreds of transactions and tables in only one data module.
This is an old application in Delphi that is being migrated to Lazarus.
There are hundreds of forms that contain between 1 and 3 tables.
Having a data module for each form would be a huge waste of resources.
In addition, there is only one connection for each database in the central data module. We only create an individual data module for each form when it needs many tables. Even in this case, the individual data module uses one of the connections that are in the central data module.

mangakissa

  • Hero Member
  • *****
  • Posts: 1101
Re: Error - Transaction of connection not set
« Reply #4 on: September 01, 2018, 10:02:39 pm »
The whole idea of using databases and GUI is seperating those things . Your form doesn't have to know how your query is connected.
Quote
I can't have dozens of connections and hundreds of transactions and tables in only one data module.
Your wrong. One datamodule is is global and runinng the connection. All other queries for each form can have his own datamodule.
Quote
Having a data module for each form would be a huge waste of resources.
That's only when you open them all at once. Just create the datamodule when you open your form.
Quote
This is an old application in Delphi that is being migrated to Lazarus.
So the developping of the program was wrong in the beginning.
Quote
n addition, there is only one connection for each database in the central data module. We only create an individual data module for each form when it needs many tables. Even in this case, the individual data module uses one of the connections that are in the central data module.
First you tell all datacomponents ar on the form. Second you tell there's a an individual datamodule for each form. I'm confused write now.

I'll give an solution bases on your example.

I create a a large application over 60 forms and use 10 to 12 datamodules. I'm just open the datamodule I need for the form. All my connections to the database (except Tdatasource) doesn't know nothing about my databas. When I want a form rebuild, the connection the the database will be the same. Just connecting the form to the datamodule.

My approach is: Form  <--> class object <--> datamodule

Lazarus 2.06 (64b) / FPC 3.0.4 / Windows 10
stucked on Delphi 10.3.1

sash

  • Sr. Member
  • ****
  • Posts: 366
Re: Error - Transaction of connection not set
« Reply #5 on: September 01, 2018, 11:22:34 pm »
Try to explicitly set a Connection+Transaction for a Query in Form2.OnCreate.
Lazarus 2.0.10 FPC 3.2.0 x86_64-linux-gtk2 @ Ubuntu 20.04 XFCE

taazz

  • Hero Member
  • *****
  • Posts: 5365
Re: Error - Transaction of connection not set
« Reply #6 on: September 02, 2018, 12:35:31 am »
Why IBConnection component looses its information about the default SQLTransaction component after first run?

Important detail: I am using a second SQLTransaction for a SQLQuery.

I have attached a small example:
- Run the project;
- Click Button1 to open Form2;
- Click Button3 to run query. It works correctly;
- Close Form2;

- Click Button1 AGAIN to reopen Form2;
- Click Button3 to run query. It gives error "Transaction of connection not set".

EDatabaseError, SErrConnTransactionnSet, Transaction of connection not set
It is not a bug it is by design. When TSQLtransaction frees it self all controls that registered with its destruction mechanism are informed so they can react. TIBConnection at that point cleans up the internal field to avoid random memory access errors. Try to change the onclose action to caHide instead or even better do not use the form2's transaction as the default transaction of the database use it only as the transaction of the queries on form2.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

valdir.marcos

  • Hero Member
  • *****
  • Posts: 1008
Re: Error - Transaction of connection not set
« Reply #7 on: September 02, 2018, 06:24:43 am »
The whole idea of using databases and GUI is seperating those things . Your form doesn't have to know how your query is connected.
I agree.

Quote
Quote
I can't have dozens of connections and hundreds of transactions and tables in only one data module.
Your wrong. One datamodule is is global and runinng the connection. All other queries for each form can have his own datamodule.
Which side do you put the transaction in?

Quote
Quote
Having a data module for each form would be a huge waste of resources.
That's only when you open them all at once. Just create the datamodule when you open your form.
Considering that most of the forms of the project deals with three or less tables. Instead of heaving more than one thousand files (forms) in the project, do you suggest to have more than two thousand files (forms and data modules)?

Quote
Quote
This is an old application in Delphi that is being migrated to Lazarus.
So the developping of the program was wrong in the beginning.
I don't agree.

Quote
Quote
n addition, there is only one connection for each database in the central data module. We only create an individual data module for each form when it needs many tables. Even in this case, the individual data module uses one of the connections that are in the central data module.
First you tell all datacomponents ar on the form. Second you tell there's a an individual datamodule for each form. I'm confused write now.
Not all situations are equal:
- Central data module for connections without central transaction;
- Individual transactions on forms or individual data modules;
- Small quantity of tables, viewes or stored procedures WITHOUT individual data module;
- Big quantity of tables, viewes or stored procedures WITH individual data module;

taazz

  • Hero Member
  • *****
  • Posts: 5365
Re: Error - Transaction of connection not set
« Reply #8 on: September 02, 2018, 06:48:54 am »
Considering that most of the forms of the project deals with three or less tables. Instead of heaving more than one thousand files (forms) in the project, do you suggest to have more than two thousand files (forms and data modules)?

No, by converting them to datamodules you will have the opportunity to use a single datamodule for multiple forms for example if the only difference between the 10 datamodules is the select query then create a single datamodule, pass that query as a parameter at the module's creation time and use it from the 10 different forms. If everything else fails then yes having 2000 files instead of 1000 forms is the recomended approach that will allow you to easily replace the forms when needed, eg when you target a different operating system or device (mobile, android, IOS etc).

It all depends on the details though.

Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

valdir.marcos

  • Hero Member
  • *****
  • Posts: 1008
Re: Error - Transaction of connection not set
« Reply #9 on: September 02, 2018, 07:01:17 am »
I'll give an solution bases on your example.
I create a a large application over 60 forms and use 10 to 12 datamodules.
We do not have the same audience.
I consider a small application when it has up to 500 files (forms, data modules and reports). A medium size up to 1,000 files. And a big one upwards.
A similar idea may be considerated for their databases: a small database contains up to 500 objects (tables, views and stored procedures). A medium size up to 1,000 objects. And a big one upwards.
Just as an example of my métier, a small ERP usually has around 1,000 files (forms, data modules and reports) and 1,000 objects (tables, views and stored procedures).

Quote
I'm just open the datamodule I need for the form. All my connections to the database (except Tdatasource) doesn't know nothing about my databas. When I want a form rebuild, the connection the the database will be the same. Just connecting the form to the datamodule.
My approach is: Form  <--> class object <--> datamodule
I agree with you for new long projects with high prepared team. I really like OPF (Object Persistence Framework)

Coming back to reality, I have many constraints, including budget and deadline.

valdir.marcos

  • Hero Member
  • *****
  • Posts: 1008
Re: Error - Transaction of connection not set
« Reply #10 on: September 02, 2018, 07:02:45 am »
Try to explicitly set a Connection+Transaction for a Query in Form2.OnCreate.
It's already done visually on Object Inspector.

valdir.marcos

  • Hero Member
  • *****
  • Posts: 1008
Re: Error - Transaction of connection not set
« Reply #11 on: September 02, 2018, 07:16:36 am »
Why IBConnection component looses its information about the default SQLTransaction component after first run?
It is not a bug it is by design.
Are you sure?

Quote
When TSQLtransaction frees it self all controls that registered with its destruction mechanism are informed so they can react. TIBConnection at that point cleans up the internal field to avoid random memory access errors.
I have destroyed and recreated the form, how is the information present on the first instance, but it just does not exist on next instances?
It worked correctly on first run. Why it does not run correctly after destruction and recriation?

Quote
Try to change the onclose action to caHide instead
What will hapen to memory if I don't destroy objects all day long?

Quote
or even better do not use the form2's transaction as the default transaction of the database
Revisit the sample project. Form2's transaction is not the default transaction of the connection.

Quote
use it only as the transaction of the queries on form2.
It already is.

taazz

  • Hero Member
  • *****
  • Posts: 5365
Re: Error - Transaction of connection not set
« Reply #12 on: September 02, 2018, 07:36:06 am »
Why IBConnection component looses its information about the default SQLTransaction component after first run?
It is not a bug it is by design.
Are you sure?
97% sure yes.
Quote
When TSQLtransaction frees it self all controls that registered with its destruction mechanism are informed so they can react. TIBConnection at that point cleans up the internal field to avoid random memory access errors.
I have destroyed and recreated the form, how is the information present on the first instance, but it just does not exist on next instances?
It worked correctly on first run. Why it does not run correctly after destruction and recriation?

The first time it is executed, the settings where loaded from the lfm resources, and I assume some sort of delayed assignment is setup(I do not remember the exact details how this works you need to verify it).
The Transaction's onDestroy even has not been executed yet, after form2 is created the delayed assignment is executed and the link is now complete.
When the the Teansaction is destroyed as a result of the caFree action, the connection gets informed and reacting on the event it destroys any and all links to a dead object, subsequent call to TForm2.Create do not have any info to link the two components again.

The mechanism is used primarily on the IDE designer when you delete a linked transaction all objects that are linked to it are informed and instead of a SigSegV error they clean up their internal fields. For that I'm 100% sure.


Quote
Try to change the onclose action to caHide instead
What will hapen to memory if I don't destroy objects all day long?
I can not answer that, I can only say that if care is taken to close the queries in the onclose event then the used memory should not change that much except if there are memory leaks somewhere.

Quote
or even better do not use the form2's transaction as the default transaction of the database
Revisit the sample project. Form2's transaction is not the default transaction of the connection.
Yes it is, see attached image.
Quote
use it only as the transaction of the queries on form2.
It already is.
then why you need it to be the default transaction of the connection?
« Last Edit: September 02, 2018, 07:40:13 am by taazz »
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

valdir.marcos

  • Hero Member
  • *****
  • Posts: 1008
Re: Error - Transaction of connection not set
« Reply #13 on: September 02, 2018, 07:52:24 am »
Considering that most of the forms of the project deals with three or less tables. Instead of heaving more than one thousand files (forms) in the project, do you suggest to have more than two thousand files (forms and data modules)?
No, by converting them to datamodules you will have the opportunity to use a single datamodule for multiple forms for example if the only difference between the 10 datamodules is the select query then create a single datamodule, pass that query as a parameter at the module's creation time and use it from the 10 different forms.
This is not compliant to the KISS principle.
Here in Brazil, your suggestion would be considered "Programação Orientada a Gambiarras (POG)", something similiar to "Workaround-Oriented Programming (WOP).  :)

Quote
If everything else fails then yes having 2000 files instead of 1000 forms is the recomended approach that will allow you to easily replace the forms when needed, eg when you target a different operating system or device (mobile, android, IOS etc).
It all depends on the details though.
This small ERP was created using Borland Delphi 2 (1996), more than 20 years ago.
And upgraded up to Borland Delphi 7 (2002), more than 15 years ago.
Since then, this application is only maintained using Delphi 7.
Now it is being migrated to Lazarus. It will not be rewritten from scratch, it will only be migrated in the simplest way for the shortest possible time and at the lowest possible cost.
After that, it will be rewritten for internet (most likely PHP) and mobile (most likely Kotlin and Swift) and it will die for the Desktop version within a few years.
It's sad, but new programmmers don't learn Pascal in college anymore.

valdir.marcos

  • Hero Member
  • *****
  • Posts: 1008
Re: Error - Transaction of connection not set
« Reply #14 on: September 02, 2018, 07:59:20 am »
Why IBConnection component looses its information about the default SQLTransaction component after first run?
It is not a bug it is by design.
Are you sure?
97% sure yes.

Quote
When TSQLtransaction frees it self all controls that registered with its destruction mechanism are informed so they can react. TIBConnection at that point cleans up the internal field to avoid random memory access errors.
I have destroyed and recreated the form, how is the information present on the first instance, but it just does not exist on next instances?
It worked correctly on first run. Why it does not run correctly after destruction and recriation?

The first time it is executed, the settings where loaded from the lfm resources, and I assume some sort of delayed assignment is setup(I do not remember the exact details how this works you need to verify it).
The Transaction's onDestroy even has not been executed yet, after form2 is created the delayed assignment is executed and the link is now complete.
When the the Teansaction is destroyed as a result of the caFree action, the connection gets informed and reacting on the event it destroys any and all links to a dead object, subsequent call to TForm2.Create do not have any info to link the two components again.

The mechanism is used primarily on the IDE designer when you delete a linked transaction all objects that are linked to it are informed and instead of a SigSegV error they clean up their internal fields. For that I'm 100% sure.
This is very bad news.

 

TinyPortal © 2005-2018