[Gambas-user] WITH and FOR EACH across emulated collections (large post)
Fabien Bodard
gambas.fr at ...626...
Mon Dec 27 09:51:51 CET 2010
2010/12/27 Bruce Bruen <bbruen at ...2308...>:
>
> 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
>
> ------------------------------------------------------------------------------
> Learn how Oracle Real Application Clusters (RAC) One Node allows customers
> to consolidate database storage, standardize their database environment, and,
> should the need arise, upgrade to a full multi-node Oracle RAC database
> without downtime or disruption
> http://p.sf.net/sfu/oracle-sfdevnl
> _______________________________________________
> Gambas-user mailing list
> Gambas-user at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/gambas-user
>
>
Clearly, gambas miss a way to know the var name where are stored the
unfreed ref...
i can't find in your code where the free are not done....
--
Fabien Bodard
More information about the User
mailing list