Previously I've used wrapper transaction functions so I had a choice
how I wanted methods called, etc. Or I've moved the transactions
further and further up the calling stack.
with this example (below) ideally this should be done deep in the
database .... but I haven't that luxury in this case.
what I'll have grief with is that the "gwEval.save(dtoEval);" already
has a transaction so it'll get the correct PKey to return on the
insert. And this is just a simple example.
(NOTE: this uses anemic beans and DAO's while all my gateways are
really for Flash Remoting, not specifically query/multiple record
CFC's.)
it's the gwEval.getByFields
not finding one
returning an empty bean
and gwEval.save(dtoEval) saving the bean.
I'm reluctant to move all that deep into the DAO because either I have
to refer to the other object for that FKey value within the DAO or
pass it in (which means I may be getting it for no reason)
it's not a show-stopper - it's just I don't like any of the solutions
I've come up with so far...
thoughts?
thanx
barry.b
<cfset gwEval = createObject("component","components._evalGateway") />
<!--- START A TRANSACTION HERE (hopes) ----------->
<cfset dtoEval = gwEval.getByFields(courseID="#courseID#",
modID="#modID#").init() />
<cfif len(dtoEval.getevalID()) EQ 0 or dtoEval.getevalID() EQ 0>
<!--- empty/doesn't exist yet --->
<!--- get the default evaluation instrument (needed for a FKey) --->
<cfset dtoInst =
createObject("component","components._instGateway").getByDefault() />
<cfscript>
dtoInst.init();
dtoEval.setEvalID(0); // the flag for "create"
dtoEval.setmodID(modID);
dtoEval.setcourseID(courseID);
dtoEval.setstartdate(now());
dtoEval.setinstID(dtoInst.getInstID());
dtoEval.setevalname("Evaluation For " & modID);
dtoEval.setactive(1);
gwEval.save(dtoEval); /*** has TRANS deep inside ***/
</cfscript>
</cfif>
<!--- at this stage, dtoEval should be either fully populated with
existing data or created from default values --->
<!--- END TRANSACTION HERE (hopes) ----------->
A DAO is good until you need to manage a transaction where more than one object is involved (ie an OrderItemDAO and a TransactionDAO).
In this example you could have a method in the service layer createOrder() that begins the transaction, calls methods on all the objects it needs then closes the transaction.
Alan
________________________________________
From: cfc...@googlegroups.com [cfc...@googlegroups.com] On Behalf Of Barry Beattie [barry....@gmail.com]
Sent: 26 October 2007 07:23
To: cfc...@googlegroups.com
Subject: [CFCDEV] where to put transactions?
see, that's my point: you start off thinking "this is just simple CRUD
stuff", a new requirement comes in and the next thing you know you're
refactoring a ton of code and retesting it all... just because of
transactions and the inability to nest them.
Unfortunately there is still lots of switch and if statements after some of the refactoring.
This seemed Ok until I discovered patterns Strategy and State that could handle these situations very well.
No matter what code I write it always embarrasses me a year or so later.
It's just one of these things I think I have to live with.
Maybe the day I fully understand the book 'Design Patterns' will be the day my code will age well :-)
________________________________________
From: cfc...@googlegroups.com [cfc...@googlegroups.com] On Behalf Of Barry Beattie [barry....@gmail.com]
Sent: 26 October 2007 18:02
To: cfc...@googlegroups.com
Subject: [CFCDEV] Re: where to put transactions?
Oh wow!
What a great life-lesson. I've been pondering lately that 50% of coding
should be taking out the garbage.
Maybe another 10% should be revisiting / refactoring every 6 months.
But as I told a friend who was trying to justify a .5% tax increase:
"Hey!" I said. "I've only got a hundred of those things!"
I'm not.
I used to be but I'm taking a more pragmatic approach now-a-days.
Sending code into the big bad world, never to see it again, and having
my reputation rest on it's success or otherwise. Get it right, get it
out.
but back to the origional question: looks like there's no magic
bullet, nothing has changed since I last grappled with these problems
(except I'm using Remoting more, making the issue more accute).
it sounds like the only solution is the "big design up-front", where
processes that need to sit within a transaction can be identified and
catered for at the start. not quite as agile as I'd like...
... nesting transactions, that'd fix it. CF9 wishlist perhaps?
oh well...
thanx
barry.b
what's making it tricky is that my beans and DTO's are being generated
by FlexBuilder which I'm then mod'ing. And of course, an insert is
followed by a re-query to get the PK, thanx to the db I'm using - all
within a transaction. I can't even cheat and put both in the same
cfquery tag...
serves me right for using code generators...
no solution here ... just offloading some angst after being cought-out
yet again...