[Gambas-user] WITH and FOR EACH across emulated collections (large post)
Bruce Bruen
bbruen at ...2308...
Mon Dec 27 03:18:40 CET 2010
Hello all,
(gambas 2.22)
I am trying to build a persistence mechanism ala Ambler to decouple the
business logic from the persistence mechanism. I have done this
several times before in gambas with great success, but with the "rule" that a
business-object instance can only represent a single row in the associated
database table. However, this time I am trying to include a way to allow
a single business-object instance to represent a set of database rows and
to provide the means to enumerate across the rows. In short, it changes the
business-object class into a psuedo collection.
I have attached a png showing the class structure. It has been simplified
very much to illustrate the problem I am having.
I have also attached a test project (as a "source archive") that demonstrates
the problems. These are
1) Use of "WITH" seems to decouple the _free() method
2) use of "FOR EACH ... NEXT" seems to decouple the _free() method and
introduces circular references.
The test project steps through a number of test cases. In each step, an
instance of a specific business-object class is created and an explicit
destruction request is issued
$employee = NEW Employee
...
$employee = NULL
Between these, each test demonstrates a single type of access to the
business_object class instance, for example Test3 just prints the values of
the properties of the first row encountered in the database Result.
(The Main routine includes all the "STOP"s so that the output does not become
jumbled.)
Here is the output I get (with some comments in colour):
=============================
----> Test 1 just creates a BO instance and then destroys it
BO destructor for Employee (2 references)
<---- Test 1 complete, explicit object destruction trace should be above this
line
This demonstrates that the destructor (_free) method is being called for the
explicit $employee=NULL line
=============================
----> Test 2 creates a BO instance, loads it and then destroys it
Employee Load got 3 rows
BO destructor for Employee (2 references)
<---- Test 2 complete, explicit object destruction trace should be above this
line
Loading the multiple rows occurs properly and the destruct call works
=============================
----> Test 3 creates a BO instance, loads it, uses it explicity and then
destroys it
Employee Load got 3 rows
Test 3 Ard01 Aaron Ardvaark 1001 45000
BO destructor for Employee (2 references)
<---- Test 3 complete, explicit object destruction trace should be above this
line
Here we just use the object in a simple manner, again destruct is OK
=============================
----> Test 4 creates a BO instance, loads it, uses it via WITH and then
destroys it
Employee Load got 3 rows
Test 4 Ard01 Aaron Ardvaark 1001 45000
<---- Test 4 complete, explicit object destruction trace should be above this
line
BO destructor for Employee (2 references)
Here's the first problem, just by using WITH instead of directly referencing
the object variables has caused the _free() method to not be called on
$employee=NULL (I do see that it is called when the Test4 method exits
though, i.e. the runtime does know it has to free the references somehow. But
why is the explicit destruction ignored?
=============================
----> Test 5 creates a BO instance, loads it, uses it explicity and then
destroys it (repeat Test3)
Employee Load got 3 rows
Test 5 Ard01 Aaron Ardvaark 1001 45000
BO destructor for Employee (2 references)
<---- Test 5 complete, explicit object destruction trace should be above this
line
This was just included to prove to myself that everything is still ok.
=============================
----> Test 6 creates a BO instance, loads it, enumerates the set (using FOR
EACH & explicit property name) and then destroys it
Employee Load got 3 rows
Test 6 Ard01 Aaron Ardvaark 1001 45000
Test 6 Ban01 Bev Banana 1001 48500
Test 6 Fri01 Fanny Fricassee 1001 38920
<---- Test 6 complete, explicit object destruction trace should be above this
line
Here the explicit and implicit destructions are both ignored ( and this causes
the final error below)
=============================
----> Test 7 creates a BO instance, loads it, enumerates the set (manually)
and then destroys it
Employee Load got 3 rows
Test 7 0 Ard01 Aaron Ardvaark 1001 45000
Test 7 1 Ban01 Bev Banana 1001 48500
Test 7 2 Fri01 Fanny Fricassee 1001 38920
BO destructor for Employee (2 references)
<---- Test 7 complete, explicit object destruction trace should be above this
line
In this final test, where I use MoveNext rather than FOR EACH, everything
appears OK.
=============================
WARNING: circular references detected
_pEmployee (1)
Employee (1)
WARNING: 49 allocation(s) non freed.
When the program exits, I get the circular references problem
Hopefully, I have packed up the test project correctly and some kind soul will
confirm the above and be able to reply with what it is that I am doing wrong.
The only thing I have been able to isolate is that the circular reference
appears the second time that Unmarshall is called from the Persistor _next()
method at line 143. If this call is commented out then the circular
references do not happen. The ingorances of the $employee=NULL still continue
though.
The test project is a very cut down version of the real dev project, so some
of the constructs used may appear odd, such as the use of dynamic object
creation. Please ignore the use of these as they do make sense in the real
project and have been proven OK in the other (single row) versions of this
design. The issues lie solely with "WITH" (where I cannot see how I have
disturbed it) and with FOR EACH (where I cannot understand what is causing
the circular references).
Thank you for reading this and many thanks in advance if you could find time
to help me with this.
--
best regards
Bruce Bruen
-------------- next part --------------
Hello all,
(gambas 2.22)
I am trying to build a persistence mechanism ala Ambler to decouple the
business logic from the persistence mechanism. I have done this
several times before in gambas with great success, but with the "rule" that
a
business-object instance can only represent a single row in the associated
database table. However, this time I am trying to include a way to allow
a single business-object instance to represent a set of database rows and
to provide the means to enumerate across the rows. In short, it changes the
business-object class into a psuedo collection.
I have attached a png showing the class structure. It has been simplified
very much to illustrate the problem I am having.
[cid:183244887 at ...2520...]
I have also attached a test project (as a "source archive") that
demonstrates the problems. These are
1) Use of "WITH" seems to decouple the _free() method
2) use of "FOR EACH ... NEXT" seems to decouple the _free() method and
introduces circular references.
The test project steps through a number of test cases. In each step, an
instance of a specific business-object class is created and an explicit
destruction request is issued
$employee = NEW Employee
...
$employee = NULL
Between these, each test demonstrates a single type of access to the
business_object class instance, for example Test3 just prints the values of
the properties of the first row encountered in the database Result.
(The Main routine includes all the "STOP"s so that the output does not
become jumbled.)
Here is the output I get (with some comments in colour):
=============================
----> Test 1 just creates a BO instance and then destroys it
BO destructor for Employee (2 references)
<---- Test 1 complete, explicit object destruction trace should be above
this line
This demonstrates that the destructor (_free) method is being called for the
explicit $employee=NULL line
=============================
----> Test 2 creates a BO instance, loads it and then destroys it
Employee Load got 3 rows
BO destructor for Employee (2 references)
<---- Test 2 complete, explicit object destruction trace should be above
this line
Loading the multiple rows occurs properly and the destruct call works
=============================
----> Test 3 creates a BO instance, loads it, uses it explicity and then
destroys it
Employee Load got 3 rows
Test 3 Ard01 Aaron Ardvaark 1001 45000
BO destructor for Employee (2 references)
<---- Test 3 complete, explicit object destruction trace should be above
this line
Here we just use the object in a simple manner, again destruct is OK
=============================
----> Test 4 creates a BO instance, loads it, uses it via WITH and then
destroys it
Employee Load got 3 rows
Test 4 Ard01 Aaron Ardvaark 1001 45000
<---- Test 4 complete, explicit object destruction trace should be above
this line
BO destructor for Employee (2 references)
Here's the first problem, just by using WITH instead of directly referencing
the object variables has caused the _free() method to not be called on
$employee=NULL (I do see that it is called when the Test4 method exits
though, i.e. the runtime does know it has to free the references somehow.
But why is the explicit destruction ignored?
=============================
----> Test 5 creates a BO instance, loads it, uses it explicity and then
destroys it (repeat Test3)
Employee Load got 3 rows
Test 5 Ard01 Aaron Ardvaark 1001 45000
BO destructor for Employee (2 references)
<---- Test 5 complete, explicit object destruction trace should be above
this line
This was just included to prove to myself that everything is still ok.
=============================
----> Test 6 creates a BO instance, loads it, enumerates the set (using FOR
EACH & explicit property name) and then destroys it
Employee Load got 3 rows
Test 6 Ard01 Aaron Ardvaark 1001 45000
Test 6 Ban01 Bev Banana 1001 48500
Test 6 Fri01 Fanny Fricassee 1001 38920
<---- Test 6 complete, explicit object destruction trace should be above
this line
Here the explicit and implicit destructions are both ignored ( and this
causes
the final error below)
=============================
----> Test 7 creates a BO instance, loads it, enumerates the set (manually)
and then destroys it
Employee Load got 3 rows
Test 7 0 Ard01 Aaron Ardvaark 1001 45000
Test 7 1 Ban01 Bev Banana 1001 48500
Test 7 2 Fri01 Fanny Fricassee 1001 38920
BO destructor for Employee (2 references)
<---- Test 7 complete, explicit object destruction trace should be above
this line
In this final test, where I use MoveNext rather than FOR EACH, everything
appears OK.
=============================
WARNING: circular references detected
_pEmployee (1)
Employee (1)
WARNING: 49 allocation(s) non freed.
When the program exits, I get the circular references problem
Hopefully, I have packed up the test project correctly and some kind soul
will confirm the above and be able to reply with what it is that I am doing
wrong.
The only thing I have been able to isolate is that the circular reference
appears the second time that Unmarshall is called from the Persistor _next()
method at line 143. If this call is commented out then the circular
references do not happen. The ingorances of the $employee=NULL still
continue though.
The test project is a very cut down version of the real dev project, so some
of the constructs used may appear odd, such as the use of dynamic object
creation. Please ignore the use of these as they do make sense in the real
project and have been proven OK in the other (single row) versions of this
design. The issues lie solely with "WITH" (where I cannot see how I have
disturbed it) and with FOR EACH (where I cannot understand what is causing
the circular references).
Thank you for reading this and many thanks in advance if you could find time
to help me with this.
--
best regards
Bruce Bruen
-------------- next part --------------
A non-text attachment was scrubbed...
Name: class diagram.png
Type: image/png
Size: 52337 bytes
Desc: not available
URL: <http://lists.gambas-basic.org/pipermail/user/attachments/20101227/7bb982dd/attachment.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: phDB6a-0.0.19.tar.gz
Type: application/x-compressed-tar
Size: 34516 bytes
Desc: not available
URL: <http://lists.gambas-basic.org/pipermail/user/attachments/20101227/7bb982dd/attachment.bin>
More information about the User
mailing list