I agree that for the most part the implementing developer of the CFC
shouldn't need to worry about transactions - for the most part I wonder
if they even need to know that there's a database.  ;^)

I'm new to OO and struggled with this as well.  I ended up with (perhaps
a poor) model that seems to do it.  In my case I first dealt with this
because of recursive calls.  For example a component might, as a
property, link to another (a parent or a child).  When I delete one I
wanted to cascade the delete to the children.

In my case all of my persistent methods call out to external includes.
A "datasource" component determines which include file to call (this way
the same object model can support pretty much any persistence method).
The call uses an "internal" argument "RecursiveCall" like this:

<cfif arguments.RecursiveCall>
        <cfinclude
template="DB_#this.DPDataSource.getType()#\Venue_save.cfm">
<cfelse>
        <cftransaction action="BEGIN" isolation="SERIALIZABLE">
                <cfinclude
template="DB_#this.DPDataSource.getType()#\Venue_save.cfm">
        </cftransaction>
</cfif>

So a transaction is begun only when called from outside.  When called
from inside the internal argument is used.  Since the DB logic is out in
an include file there's no complexity in setting the transaction or not.

I had also considering using the current taglist to determine if we were
in a transaction... but that seemed heavy to me.

It would be nice if the CFTransaction tag had some sort of "continue"
action that would continue a current action or start a new one.

The main problem with this is that although this will maintain database
integrity it won't maintain the integrity of the component model.  You
have to do something to rebuild the component or otherwise deal with
things if an error occurs and you have to roll things back.

Again... this may not be a very good way to do things, but it's working
fairly well for me.

Jim Davis

> -----Original Message-----
> From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On
Behalf
> Of Nathan Dintenfass
> Sent: Tuesday, November 18, 2003 5:03 PM
> To: [EMAIL PROTECTED]
> Subject: RE: [CFCDev] cftransactions in low level modules
> 
> Can I ask: why not just build a CFC layer that exposes a simple API
that
> does the transaction internally, then have that layer make use of your
> underlying persistence mechanism?  That is, why make an end-developer
have
> to even think about transactions if they are a known quantity in
advance?
> Instead, just build one or more CFCs that are the "business layer" and
> then
> let the developer use those.  So, for instance, if you have a
persister
> with
> methods like:
> 
> insertUser(id,fname,lname,email);
> associateUserWithDepartment(userID,deptID);
> associateUserAsDirectReport(userID,bossID);
> 
> and you have a transaction, which will be "insert a user and associate
> him/her with a given department and make them a direct a report of
another
> given user" you can have your persister layer expose a granular API
that
> is
> transaction agnostic, then build a UserManager.cfc (or whatever) that
has
> a
> method like:
> 
> saveUser(user,deptID,directReportID);
> 
> Your saveUser method can then call the methods of the persister in a
> transaction.
> 
> I am no OO expert, but in my experience thus far with CFCs I find it's
> generally best to not have the end-developer interact directly with a
> persistence layer in anything other than the simplest systems,
preferring
> instead to encapsulate that complexity with a higher-order API.
> 
> Or, am I missing the boat here?
> 
>  - Nathan
> 
> 
> 
> 
> 
> 
> 
> > -----Original Message-----
> > From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]
> > Behalf Of Barney Boisvert
> > Sent: Tuesday, November 18, 2003 1:47 PM
> > To: [EMAIL PROTECTED]
> > Subject: RE: [CFCDev] cftransactions in low level modules
> >
> >
> > I'm not sure I have an answer to that one, as you're kind of mixing
> > different styles.  I think I'd still say that a transaction can only
be
> > controlled from the upper level, outside the function, so you'd
> > need to add
> > CFTRANSACTION tags around the first CFINVOKE, just like the second
set.
> >
> > Here's another idea:
> >
> > This is totally shooting from the hip (with code below), but what
about
> > making beginTransaction, rollbackTransaction and
> > commitTransaction functions
> > in your CFC.  Inside the function body, they'd use a
> > request-scoped flag to
> > track whether there is a transaction currently open, and would
> > only actually
> > do anything when the state changed.  Then you would call them from
> inside
> > your functions (taking care of case one), and you could also call
> > them from
> > outside the functions (case two), in which case the inside calls
> > wouldn't do
> > anything, because there is already a transaction in progress.
> >
> > function beginTransaction() {
> >   if (request.transactionNext EQ 0) {
> >     CFTRANSACTION ACTION="begin"
> >   }
> >   request.transactionNext = request.transactionNext + 1;
> > }
> >
> > function rollbackTransaction() {
> >   if (request.transactionNext EQ 0) {
> >     CFTHROW TYPE="NoValidTransactionException"
> >   }
> >   CFTRANSACTION ACTION="rollback"
> >   request.transactionNext = 0;
> > }
> >
> > function commitTransaction() {
> >   request.transactionNext = request.transactionNext - 1;
> >   if (request.transactionNext EQ 0) {
> >     CFTRANSACTION ACTION="commit"
> >   }
> > }
> >
> > > -----Original Message-----
> > > From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]
> > > Behalf Of Jay Gibb
> > > Sent: Tuesday, November 18, 2003 12:34 PM
> > > To: [EMAIL PROTECTED]
> > > Subject: RE: [CFCDev] cftransactions in low level modules
> > >
> > >
> > > Hey Barney,
> > >
> > > What about if you're not using OO modelling?  This is for a
procedural
> > > system.  A pseudo implementation might be...
> > >
> > > <!--- in one place... --->
> > > <cfinvoke method="myFunction" component="myComponent"
> > >   returnVariable="result">
> > >
> > > <!--- in another place... --->
> > > <cftransaction>
> > >   <cfinvoke method="myFunction" component="myComponent"
> > >           useTransaction="no"
> > >           returnVariable="result">
> > >
> > >   <cfinvoke method="myFunction" component="myComponent"
> > >           useTransaction="no"
> > >           returnVariable="result">
> > >
> > >   <cfinvoke method="myFunction" component="myComponent"
> > >           useTransaction="no"
> > >           returnVariable="result">
> > > </cftransaction>
> > >
> > >  - j.
> > >
> >
> > ----------------------------------------------------------
> > You are subscribed to cfcdev. To unsubscribe, send an email
> > to [EMAIL PROTECTED] with the word 'unsubscribe cfcdev'
> > in the message of the email.
> >
> > CFCDev is run by CFCZone (www.cfczone.org) and supported
> > by Mindtool, Corporation (www.mindtool.com).
> >
> > An archive of the CFCDev list is available at
> www.mail-archive.com/[EMAIL PROTECTED]
> 
> ----------------------------------------------------------
> You are subscribed to cfcdev. To unsubscribe, send an email
> to [EMAIL PROTECTED] with the word 'unsubscribe cfcdev'
> in the message of the email.
> 
> CFCDev is run by CFCZone (www.cfczone.org) and supported
> by Mindtool, Corporation (www.mindtool.com).
> 
> An archive of the CFCDev list is available at www.mail-
> archive.com/[EMAIL PROTECTED]


----------------------------------------------------------
You are subscribed to cfcdev. To unsubscribe, send an email
to [EMAIL PROTECTED] with the word 'unsubscribe cfcdev' 
in the message of the email.

CFCDev is run by CFCZone (www.cfczone.org) and supported
by Mindtool, Corporation (www.mindtool.com).

An archive of the CFCDev list is available at www.mail-archive.com/[EMAIL PROTECTED]

Reply via email to