The controller's not the place, because that's part of the UI. Transactions should be managed in your service objects.
In most cases, every method invoked on a service object from outside the service layer will be an atomic business operation that should either entirely succeed or entirely fail. That usually equates to a database transaction as well, though it can get more complex if you're changing things that aren't in a database. For example, take adding a user to a hypothetical system where very user has one or more roles associated with them. That obviously means that a user can never have zero roles, so inserting the user and assigning roles must be part of a single operation, and therefore the database interactions must take place in the same transaction (so the INSERT user statement is rolled back if the linking to the roles fails). Now it's entirely possible for the business need to change to allow users with zero roles. Where should that change happen? It's a business rule changing, so you should change it in the business layer. That's only possible if the transactionality (to coin a term) is managed by the business layer. If that change did happen, you'd take your addUser(username, roleList) method, and split it into addUser(username) and assignUserToRoles(userId, roleList) methods, leaving the original method for backwards compatibility with it's implementation changed to use the two new methods. Now that that's all done, we have the exceptions. What if you're not in a transaction (database) when you go to do your two-table updated of the museum info. You definitely want to be in one, in case the second UPDATE fails. That's a place where you'd want to have transactional awareness in your persistance layer. In other words, if only the persistance layer knows a transaction is needed should it be in charge. The highest level that knows a transaction is needed shoudl be in charge of making sure there is one. And now we arrive at what I see as a major shortcoming with CF's implementation of database transactions. Because you use a CFTRANSACTION tag with a body, you're necessarily limited in what you can do. Specifically, there's no way to say "start a transaction, unless one already exists," which is precisely what is needed for the DAO to add a transaction in the last example. If you could use self-closed tags to start/rollback/commit transactions (rather than having to nest the CFQUERY tags inside), we'd be closer, and if there were a "conditionalstart" option to the ACTION attribute, then we'd totally be covered. If you're using CFMX (not BD), you can kind of deal with that, because in the current version a given request is allocated sole access to a single DB connection for the entirety. So you can use SQL to set up your transactions manually, rather than the CFTRANSACTION tag to avoid the issue. Build in a stack manager, and you can get the conditionalStart behaviour as well. But if CF ever stops associating DB connections with requests in this fashion, that ability will magically vanish, and you'll have a totally wrecked application. cheers, barneyb On 8/19/05, Peter Hardy <[EMAIL PROTECTED]> wrote: > lol ... yay for me :) > > I like your view of transactions but am curious. In the past I've always > made a distinction between business transactions and database transactions. > The business transaction is "Did I complete TaskA and TaskB required to > complete the process" and the database transaction is "Did the inserts, > updates, deletes required for a each task work correctly". Now if TaskB is > dependant on some operations in TaskA being committed I need a transaction > somewhere. Are you suggesting it should be in my business object. Or maybe > further back still and in my controller? > > Sorry if I seem a bit befuddled but this is a bit of a head-shift for me and > it's not quite clear yet. > > Cheers, > > Pete (aka lad4bear) > -- Barney Boisvert [EMAIL PROTECTED] 360.319.6145 http://www.barneyb.com/ Got Gmail? I have 50 invites. ---------------------------------------------------------- You are subscribed to cfcdev. To unsubscribe, send an email to [email protected] with the words 'unsubscribe cfcdev' as the subject of the email. CFCDev is run by CFCZone (www.cfczone.org) and supported by CFXHosting (www.cfxhosting.com). CFCDev is supported by New Atlanta, makers of BlueDragon http://www.newatlanta.com/products/bluedragon/index.cfm An archive of the CFCDev list is available at www.mail-archive.com/[email protected]
