[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