Menu

#103 Problem disposing an TInstantObject with multiple queries

v2.0
open
nobody
5
2012-11-03
2006-07-03
No

[reported by: Stephane Carre]
We have a problem when disposing an TInstantObject
referenced in multiple queries.
It seems that the referenced object is correctly
updated in the query in which it was disposed, but not
in the other queries. It seems that Dispose effectively
creates a new object (pointer) which is no longer
referenced correctly in other queries. If we do not
dispose the object, but simply change its properties,
the change is correctly seen in all queries of course,
as the referenced object pointer is unchanged.

The following code explains what we want to do (and
hopefully allows you to reproduce the problem).
Additionally we use the safe typecast operator, but it
does not have an impact.

procedure TMyInstantObjectTests.TestDoubleReferenceQuery;
var
MyInstantObject: TMyInstantObject;
Query1, Query2: TInstantQuery;
i: integer;
begin
MyInstantObject := TMyInstantObject.Create(Connector);
MyInstantObject.SomeProperty := 'Test0';
MyInstantObject.Store;
FreeAndNil(MyInstantObject);

MyInstantObject := TMyInstantObject.Create(Connector);
MyInstantObject.SomeProperty := 'Test1';
MyInstantObject.Store;
FreeAndNil(MyInstantObject);

MyInstantObject := TMyInstantObject.Create(Connector);
MyInstantObject.SomeProperty := 'Test2';
MyInstantObject.Store;
FreeAndNil(MyInstantObject);

try
Query1 := Connector.CreateQuery;
Query1.Command := 'SELECT * FROM TMyInstantObject';
Query1.Open;

CheckEquals(3,Query1.ObjectCount,'Query1.ObjectCount
error');

Query2 := Connector.CreateQuery;
Query2.Command := 'SELECT * FROM TMyInstantObject';
Query2.Open;

CheckEquals(3,Query2.ObjectCount,'Query2.ObjectCount
error');

(Query1.Objects[0] as TMyInstantObject).Dispose;

//The following code works just fine, as can be

expected
//since dispose puts the referenced object in a
'newly created'
//state
CheckFalse((Query1.Objects[0] as
TMyInstantObject).IsPersistent,
'Query1.Objects[0] IsPersistent error');

//The following code does not work: trying to

access the object
//referenced in Query2 gives an Access Violation
CheckFalse((Query2.Objects[0] as
TMyInstantObject).IsPersistent,
'Query2.Objects[0] IsPersistent error');

finally
//Cleanup DB after test
Query1.Close;
Query1.Open;

for i := pred(Query1.ObjectCount) downto 0 do
  TMyInstantObject(Query1.Objects[i]).Dispose;

FreeAndNil(Query1);
FreeAndNil(Query2);

end;
end;

Discussion


Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.