For instance, consider a Contact object with an address, a couple of phone numbers and two email addresses. As things stand now, when I save a contact Record object, the Contact is saved, then the address, phone numbers, and email addresses, each with the id for the saved contact object. If save() is called on the address before the phone numbers or emails, and it fails (from a constraint violation), those phone numbers and emails are not saved. What is saved, though, is a contact record and if any changes were made to its dependent objects the database is now in a state that is inconsistent with the in-memory model. This is caused by the fact that each object is saved in its own transaction, independent of the others, and the failure of one part (like the address) does not rollback the incomplete persistence of the contact.
What I was thinking might be possible is to have the Record object's save() method operate in two modes: one that creates a new transaction and another that works within an existing transaction. To accomodate these two modes, there would be two methods: save() and saveWithTransaction(). The save method would create a new transaction, and any dependent objects would be saved using the saveWithTransaction() method.
<cffunction name="save" returntype="void" access="public">
<cftransaction>
<cfset beforeSave()>
<cfset _getDAO().save(...)>
<cfset afterSave()>
</cftransaction>
</cffunction>
<cffunction name="saveWithTransaction" returntype="void" access="public">
<cfset beforeSave()>
<cfset _getDAO().save(...)>
<cfset afterSave()>
</cffunction>
<cffunction name="beforeSave" returntype="void" access="private">
<cfloop ...>
<cfset child.saveWithTransaction()>
</cfloop>
</cffunction>
<cffunction name="afterSave" returntype="void" access="private">
<cfloop ...>
<cfset child.saveWithTransaction()>
</cfloop>
</cffunction>
<cftransaction>
<cfset beforeSave()>
<cfset _getDAO().save(...)>
<cfset afterSave()>
</cftransaction>
</cffunction>
<cffunction name="saveWithTransaction" returntype="void" access="public">
<cfset beforeSave()>
<cfset _getDAO().save(...)>
<cfset afterSave()>
</cffunction>
<cffunction name="beforeSave" returntype="void" access="private">
<cfloop ...>
<cfset child.saveWithTransaction()>
</cfloop>
</cffunction>
<cffunction name="afterSave" returntype="void" access="private">
<cfloop ...>
<cfset child.saveWithTransaction()>
</cfloop>
</cffunction>
I'm not sure if this poses any difficulties with the existing way of doing things, or if I have missed something that renders this irrelevant. Any thoughts, folks?
--
Paul Kenney
[EMAIL PROTECTED]
http://www.pjk.us -- Reactor for ColdFusion Mailing List -- [email protected] -- Archives at http://www.mail-archive.com/reactor%40doughughes.net/

