Invalid class typecast message on opening MSQuery in DLL
Invalid class typecast message on opening MSQuery in DLL
I have a problem with opening more than one TMSQuery in DLL form (SDac ver 4.30.00.12)
Proper MSConnection is assigned to DLL's variable of TMSConnection type.
Next, this variable is assigned to MSQuery1 and MSQuery2 as "connection" property.
MSQuery1.Open - opens query, but if I try to open next Query, error message "Invalid Class Typecast" is displayed.
There is simple way to reproduce this problem. Just use demo app from SDAC Demos\Win32\Miscellaneous\Dll, place second TMSQuery component on DLL form, assign "ExternalConnection" and open query from code.
Proper MSConnection is assigned to DLL's variable of TMSConnection type.
Next, this variable is assigned to MSQuery1 and MSQuery2 as "connection" property.
MSQuery1.Open - opens query, but if I try to open next Query, error message "Invalid Class Typecast" is displayed.
There is simple way to reproduce this problem. Just use demo app from SDAC Demos\Win32\Miscellaneous\Dll, place second TMSQuery component on DLL form, assign "ExternalConnection" and open query from code.
This problem may arise if you create the TMSConnection class object in a dll and use it in an application. Methods of TMSConnection use the "as" operator which returns invalid type cast error.
To solve the problem you can use the TCustomMSConnection.AssignConnect method to assign the TMSConnection object created in dll to the TMSConnection object of application.
Also you can use the approach used in the SDAC DLL demo. You can find this demo by the following path: SDAC_InstDir\Demos\Miscellaneous\Dll.
SDAC_InstDir is the SDAC installation directory on your computer.
To solve the problem you can use the TCustomMSConnection.AssignConnect method to assign the TMSConnection object created in dll to the TMSConnection object of application.
Also you can use the approach used in the SDAC DLL demo. You can find this demo by the following path: SDAC_InstDir\Demos\Miscellaneous\Dll.
SDAC_InstDir is the SDAC installation directory on your computer.
"Invalid class typecast" revisited
The DLL example provided works fine with the TMSQuery created on the form, but I create a lot of queries just in code, as follows:
[code]mq := TMsQuery.Create(nil);
mq.Connection := ExternalMSConnection;
mq.SQL.Text := 'some select statement';
mq.Open;[/code]
When I add a button to the form fmDllMain in DLLMain.pas and put this in the OnClick:
[code]procedure TfmDllMain.Button1Click(Sender: TObject);
var mq: TMsQuery;
begin
mq := TMsQuery.Create(nil);
mq.Connection := ExternalMSConnection;
mq.SQL.Text := 'select ''Hai''';
mq.Open;
while not mq.Eof do
begin
ShowMessage(mq.Fields[0].AsString);
mq.Next;
end;
mq.Close;
mq.Destroy;
end;[/code]
Then I get an invalid typecast while a similar procedure on fmExeMain in ExeMain.pas just says "Hai", as I intended.
Is this something that can be fixed?
With regards,
Peet Terluin
[code]mq := TMsQuery.Create(nil);
mq.Connection := ExternalMSConnection;
mq.SQL.Text := 'some select statement';
mq.Open;[/code]
When I add a button to the form fmDllMain in DLLMain.pas and put this in the OnClick:
[code]procedure TfmDllMain.Button1Click(Sender: TObject);
var mq: TMsQuery;
begin
mq := TMsQuery.Create(nil);
mq.Connection := ExternalMSConnection;
mq.SQL.Text := 'select ''Hai''';
mq.Open;
while not mq.Eof do
begin
ShowMessage(mq.Fields[0].AsString);
mq.Next;
end;
mq.Close;
mq.Destroy;
end;[/code]
Then I get an invalid typecast while a similar procedure on fmExeMain in ExeMain.pas just says "Hai", as I intended.
Is this something that can be fixed?
With regards,
Peet Terluin
What I did to solve/workaround this
First of all, thanks for your quick reply.
My DLL's used to have their own TMSConnection but I started running in to "lock timeout exceeded" exceptions. (multiple users and some "heavy" batch processing going on) These errors did not occur while everything was still in one executable so I thought it might be helpful to use a single MSconnection for executable and DLL's. And I started to experiment a little. So your suggestion to create a TMSConnection object in the DLL does solve the error, but not my problem ...
But it did inspire me to the following extension of the DLL-example.
Not only is the Connection made available for use in the DLL but also functions for the creation of TMsQuery and TMsSQL.
And the transaction methods, StartTransaction, Commit and Rollback are also made available for use in the DLL.
The TAssignMsConnection declaration became something like this:
TDBConnMethod = procedure; cdecl;
TCreateMsQuery = function: TMsQuery; cdecl;
TCreateMsSQL = function: TMsSQL; cdecl;
TAssignMsConnection = procedure(Conn: TMSConnection;
cqp: TCreateMsQuery ;
cqs: TCreateMsSQL ;
DBStartTransaction, DBCommit, DBRollback: TDBConnMethod); cdecl;
The first test results are hopeful ...
With regards, Peet Terluin
My DLL's used to have their own TMSConnection but I started running in to "lock timeout exceeded" exceptions. (multiple users and some "heavy" batch processing going on) These errors did not occur while everything was still in one executable so I thought it might be helpful to use a single MSconnection for executable and DLL's. And I started to experiment a little. So your suggestion to create a TMSConnection object in the DLL does solve the error, but not my problem ...
But it did inspire me to the following extension of the DLL-example.
Not only is the Connection made available for use in the DLL but also functions for the creation of TMsQuery and TMsSQL.
And the transaction methods, StartTransaction, Commit and Rollback are also made available for use in the DLL.
The TAssignMsConnection declaration became something like this:
TDBConnMethod = procedure; cdecl;
TCreateMsQuery = function: TMsQuery; cdecl;
TCreateMsSQL = function: TMsSQL; cdecl;
TAssignMsConnection = procedure(Conn: TMSConnection;
cqp: TCreateMsQuery ;
cqs: TCreateMsSQL ;
DBStartTransaction, DBCommit, DBRollback: TDBConnMethod); cdecl;
The first test results are hopeful ...
With regards, Peet Terluin