Page 1 of 2

passing connection from queries

Posted: 19.11.2019, 14:39
by DavideAmelio
Hello, what is the best way to pass the connection information from one Query to Another....the connection property is type of AbstractConnection and not as TZConnection...

Thanks Advance

Re: passing connection from queries

Posted: 19.11.2019, 15:30
by aehimself
TZConnection is a child class of TAbstractConnection. You simply can do (what I'm doing awfully a lot):

Code: Select all

Var
 query: TZQuery;
Begin
 query := TZQuery.Create(nil);
 Try
  query.Conection := ZQuery1.Connection;
[...]
Just keep thread safety in your mind: one connection can do only one thing at a time; you can not download a huge BLOB field and update an other table at the same time. This also includes .Ping (and therefore possibly other methods too): I already messed up queries when the main form was periodically pinging the connection and a modal dialog was trying to download a table.

Re: passing connection from queries

Posted: 19.11.2019, 16:31
by DavideAmelio
Thanks for reply, because i have a common unit library with a lot of many DB generic function, each of this has as parameter TZCOnnection, but i can not pass Query.connection because it's an abstractConnection type. So you suggest to change parm type to AbstractConnection? Is then possibile create a connection from AbstractConnection passed?

If i understand what you sayed : i have to create a connection each query, but is the best way in an application?

Thanks again for your support

Re: passing connection from queries

Posted: 19.11.2019, 23:56
by aehimself
That's odd, you are right. Since TZConnection inherits directly from TAbstractConnection it should work, but it does not.

Simply cast the ZQuery.Connection to TZConnection and your code should run just fine:

Code: Select all

procedure TForm2.SetToQuery(inQuery: TZQuery; inConnection: TZConnection);
begin
 inQuery.Connection := inConnection;
end;

procedure TForm2.Button1Click(Sender: TObject);
begin
 SetToQuery(ZQuery2, TZConnection(ZQuery1.Connection));
end;

Re: passing connection from queries

Posted: 20.11.2019, 08:14
by Fr0sT
Umm... What's the problem?

Code: Select all

var
  Query: TZQuery;
  Query1: TZQuery;
begin
  Query1.Connection := Query.Connection; // OK

Re: passing connection from queries

Posted: 20.11.2019, 09:37
by aehimself
Fr0sT wrote:Umm... What's the problem?
In my example SetToQuery(ZQuery2, ZQuery1.Connection); will not compile.

@DavideAmelio:
If you have a method with a TZConnection input parameter, it will not accept a TZQuery.Connection property because it is defined as TZAbstractConnection. Due to inheritance all TZConnection is TZAbstractConnection but not all TZAbstractConnection *might* be TZConnection.

But since there are no other descendants, we safely can typecast it without causing an exception.

Re: passing connection from queries

Posted: 20.11.2019, 15:07
by marsupilami
aehimself wrote:But since there are no other descendants, we safely can typecast it without causing an exception.
Erm - there is TZPooledConnection...

Re: passing connection from queries

Posted: 20.11.2019, 15:20
by aehimself
marsupilami wrote:Erm - there is TZPooledConnection...
Note to self: next time check before I say something :)

At the moment there are 2 classes inheriting from TZAbstractConnection (therefore can be set as Connection for a TZQuery):
- TZConnection
- TZGroupedConnection

I could not find any traces of TZPooledConnection.

If @DavideAmelio is not using grouped connections, the code will still work without errors. If yes, then the TZConnection parameters must be changed to TZAbstractConnection.

Re: passing connection from queries

Posted: 20.11.2019, 16:27
by DavideAmelio
@ aehimself Perfect ! Thank you

So the perfect way of programming is

- DataModule with Just ONE ZConnection
each use of Query setting as connection the DataModule.ZConnection ?
Now casting works but very I receive often the "MySql as gone away" message

should i use Query.connection := Datamodule.Connection instead?

Sorry and thank for you time

Re: passing connection from queries

Posted: 20.11.2019, 16:54
by Fr0sT
I still couldn't get what exactly is the problem. TZAbstractConn := TZConn should always work

Re: passing connection from queries

Posted: 20.11.2019, 17:32
by DavideAmelio
Fr0sT wrote:I still couldn't get what exactly is the problem. TZAbstractConn := TZConn should always work
The problem is the opposite: TZconn := TZQuery.Connection ( Abstract )
because my DB functions unit paramaters as always a connection, i was used to pass the ZQuery.connection, now thanks aehimself i pass the casted connection but after few minutes i gave a "MySql as gone away" message.

Is that because the connection is Abstract ? does mean different if I pass the TZConnection instead ?

Re: passing connection from queries

Posted: 20.11.2019, 18:47
by aehimself
DavideAmelio wrote:i pass the casted connection but after few minutes i gave a "MySql as gone away" message.
Ooooh, the good old gone away.
- What version of libmysql.dll are you using? I had this issue with 5.x. Also, give libmariadb.dll a try; sometimes it tends to be more stable.
- What is the query timeout defined on the server?
- Don't forget to keep the connection alive with periodic .Ping, otherwise your session will time out.
- Are you 100% sure that you are not doing something else with the connection in the same time? If you don't respect thread safety, the server might kick you off, resulting the same message

Re: passing connection from queries

Posted: 20.11.2019, 19:55
by DavideAmelio
libmySQL51.dll

server is setted well, ( 28800 ) infact the same application of WinXp never expired
i upgrade from zeos 6.2 to 7.2 only for fixing this problem...and i discover the difference from zQry.Connection to zQry.AbstractConnection...

Of course i have a timer that ping each minute...but on Win10 after few minutes (MySql..as gone away....)

About doing more query at the same time with the same connection...could be, So I have to use different connection on each form?

thanks

Re: passing connection from queries

Posted: 20.11.2019, 22:13
by aehimself
DavideAmelio wrote:libmySQL51.dll
Upgrade. Quickly :) See here.
DavideAmelio wrote:Of course i have a timer that ping each minute...
Do you disable the timer when you pass the connection to an other form and do something else on it? Remember, one connection can do one thing at a time. If you have a query running on the secondary form and the timer on the first form pings, the query on the secondary form will fail with the very message you try to avoid.
DavideAmelio wrote:About doing more query at the same time with the same connection...could be, So I have to use different connection on each form?
Well, yes, and no - that depends on what your application is doing. I am using only one connection in my database client application which has 4 modal popups for specific tasks, and it works well. But I'm really careful to pay attention to the multithreading best practices.

Re: passing connection from queries

Posted: 21.11.2019, 08:12
by Fr0sT
DavideAmelio wrote:The problem is the opposite: TZconn := TZQuery.Connection ( Abstract )
Why not change type of parameters in your functions to TZAbstractConn? This would be more correct from the point of class hierarchy