Doug,

Here are my opinions FWTW.

I'm glad you re-enabled the record caching.

I understand that there are issues with it. But, without it, I would have much bigger issues.

Because, these linked record objects are tied into and controlled by reactor, unless I don't use the get[relatedrecord]() mechanism, then I need reactor to provide a caching mechanism.
If there is a flushing mechanism or whatever, that's fine.
But, I would like to be able to cache a (for instance) reactor customer object, the first time this object is displayed, then several queries would be run to get related addresses and whatnot.
However, until I invalidate this cached object, I would prefer that the next time it gets displayed there is little to no database activity.

And in regards to your whole "setting values into related objects and then saving" thing. I really don't mind creating an address object, populating it, saving it, then creating a user record, and setting the address ID into it from the newly created Address. So, you can implement that whole save() on the root saves related record thing and it will be cool, but, I don't know if I would use it.

And lastly, I'm pretty sure it would be BAD if you made it so that a delete() call didn't actually delete it until something else happened. Delete() should do just that, at least IMHO.

Thank you so much for all your hard work Doug.
And thanks for asking for our opinions.

Chris Phillips

On 4/16/06, Doug Hughes <[EMAIL PROTECTED] > wrote:

FYI – I committed these changes.  However, since committing them I reneged and re-enabled the record caching.  When you call getXyz the XyzRecord object is again cached in the object. However, if you call setXyzId() it will intelligently reset the XyzRecord.  (this update has been committed)

 

The reason I decided to change my approach (again) is because of the following example.  Without caching anything, how many queries would have been run?  (Not including loading the User) 

 

<cfoutput>

            #User.getAddress().getStreet()#<br>

            #User.getAddress().getCity()#

            #User.getAddress().getStateProv().getName()#

            #User.getAddress().getPostalCode()#

#User.getAddress().getCountry().getName()#

</cfoutput>

 

Answer: 7!!  5 times for getAddress() and 1 time for getStateProv() and getCountry()

 

By re-enabling caching that 7 can be brought down to 3.  I'm not much of a fan of the fact that getStateProv and getCountry run a query… but at least once they're run they're cached!  And it's not that much data anyhow.  It feels acceptable. 

 

The big problem I see now is this code:

 

<cfset User = reactor.createRecord("User") />

<cfset User.setFirstName("Doug") />

<cfset User.getAddress().setStreet("134 Happy Street") />

 

<!--- assume the rest of the props are set for both the user and address --->

 

<cfset User.save() />

 

It feels like this should save the address too.  (I'm working on this.)  Furthermore, what if the user and address are both new?  The address needs to be saved first and it's addressId needs to be set into the user's addressId before the user is saved.

 

Or what about this:

 

<cfset User.getAddress().delete() />

 

What happens in the user?!  I've got no clue.  Maybe I could automate the process of adding event handlers so that the User could listen for certain events on the address and could catch that the address was deleted and set its own addressId to 0 and remove its reference to the address.  (Right now the User.getAddressId() would be n while the Address.getAddressId() would be 0).

 

Or maybe the delete method doesn't DO anything until later?  IE maybe I can delete it, but I have to call commit to delete it?  I suppose that's still the same problem.

 

There're a lot of big what-ifs when you start messing around in this stuff.  Any feedback would be wonderful.

 

Doug

 

 


From: [EMAIL PROTECTED] [mailto: [EMAIL PROTECTED]] On Behalf Of Doug Hughes
Sent: Saturday, April 15, 2006 12:11 PM
To: [email protected]


Subject: [Reactor For CF] Imporant changes commng to reactor this weekend

 

Everyone –

 

This message is to let you know of the following changes that *will* break your code.  These changes will be published some time today or tomorrow.  (As soon as I get them working with two of my projects and the samples.)  The changes are:

 

For a month or so now I've had record objects cache the in instance variables the results of calling getXyzRecord() or getXyzIterator() or getXyzLookup().  This has caused me no end of headaches that I've been trying to ignore but which have ticked me off enough to finally make me do something about it. 

 

Here's an example of the issue:  I have a UserRecord that hasOne AddressRecord that hasOne CountryRecord.  When the User logs in their corresponding UserRecord is stored in their session.  The user goes to edit their profile to change their address.  They view their profile and see all the correct information.  They edit their country and change it from the UK to the USA.  They click the save button.  The page refreshes and they see…. The UK.  HUH?  It's been updated in the database! 

 

The problem is this:  The UserRecord caches the AddressRecord into the variables scope (which is persistent because the user is in the session) when you call getAddressRecord.  When you call getCountryRecord() on the AddressRecord the CountryRecord is cached too.  So, let's say you update the AddressRecord and set the CountryId from 1 to 2.  Wouldn't you expect the results of calling getCountryRecord() to reflect the correct record?  I would!  But it doesn't because the CountryRecord is cached and is not refreshed automatically when you set the countryId.

 

I know I could have chosen to have reactor generate code that would invalidate the cached CountryRecord when the countryId was changed in the AddressRecord.  However, this didn't smell right to me.  It seemed to be adding complexity to the Record that's not needed.  Furthermore, there were even more issues when working with Iterators.  (You can only set the sort by one time! If it's cached you're hosed!)  So to be consistent, at least for now, I've removed the caching and the related headaches.

 

The other thing I've done:  I've dropped the Record off the getXyzRecord method.  It now will be getXyz.  I know there is a lot of controversy over this.  I've given this a lot of thought and I sincerely feel that this is the best approach.  My logic is that you don't ask the reactorFactory for an XyzRecord, you ask it for an Xyz.  IE:  reactorFactor.createRecord("xyz"), not "xyzRecord".  I've toyed with this in my code and it seems to feel better and smell better. 

 

This raises the question of what will happen to the iterator's naming convention.  For now nothing.  But, it's something I'm going to have a hard eye on.

 

FYI – the blog and contactmanager samples have been updated.  The docs HAVE NOT.

 

Doug

-- Reactor for ColdFusion Mailing List -- [email protected] -- Archives at http://www.mail-archive.com/reactor%40doughughes.net/ -- Reactor for ColdFusion Mailing List -- [email protected] -- Archives at http://www.mail-archive.com/reactor%40doughughes.net/



--
Chris Phillips
www.dealerpeak.com
Senior Application Developer -- Reactor for ColdFusion Mailing List -- [email protected] -- Archives at http://www.mail-archive.com/reactor%40doughughes.net/

Reply via email to