Update / Insert Transactions

Update / Insert Transactions

Old forum URL: forums.lhotka.net/forums/t/6214.aspx


jfreeman posted on Tuesday, January 20, 2009

I have a scenario where I want to insert records in a changes table when a record is updated in a primary table that meets certain criteria.  I need both tables to be rolled back if an error occurs on either of them.  How is the best way to call the Insert on the change table?  Thanks.

Jonathan

rsbaker0 replied on Tuesday, January 20, 2009

There are several ways to do this. 

CSLA supports a TransactionScope (sic?) attribute which can provide for "automatic" transaction management of a method so tagged, so that if you throw an exception during it's execution any updates it peformed would automatically be rolled back.

In our application, we manually manage our transactions (e.g. create a TransactionContext and do the work in a using block), and the transaction will roll itself back when disposed unless it was previously committed.

So, with either of these methods you can update your "changes" table in your DataPortal_Update method on your primary table BO . The changes table update can be done via direct SQL, by using a CSLA "child" collection corresponding to the changes to be saved, or by the stored procedure that updates the primary table if you are using stored procedures for everything.

 

 

jfreeman replied on Thursday, January 22, 2009

Could you explain a little about how the "child" collection piece would work?  When I call Update on my primary BO, all the data is on that object.  I then want to check certain criteria and update the changes table (and possibly another table) with the information from my primary BO.  How would I update using a child collection?  Thanks.

Jonathan

rsbaker0 replied on Thursday, January 22, 2009

I have my pre-CSLA 3.5 hat on here, so this may not completely apply if you are familiar with the child data portal.

When you call Save() on your primary BO, this ends up as a call to your DataPortal_Update() override that is executed server side.

Your BO can execute arbitrary updates in the process of saving itself. It is also responsible for saving any child objects, which can include child collections. Typically, child collections are derived from BusinessListBase (BLB).

So, I was suggesting that one possible implementation would be for you to have some sort of "Changes" child object (e.g. TableName, FieldName, OriginalValue, NewValue, ChangeDate, ChangeUserId, etc.) that also knows how to save itself (just one INSERT into your changes table).

Then your root BO could have a a ChangesList object derived from BLB, and as you examine your object you could construct and add Changes objects to your ChangesList. When you are done, you can write your primary BO to the database, and then also "Save" the ChangesList.

I put "Save" in quotes because I do manual transaction management, so all of my BO and BLB derived classes do the actual database updates via an internal "Update" method that takes a transaction context (my own flavor of one) as a parameter. These are always called on the server side of the data portal, and come in very handy when you want to start composing transactions that consist of multiple objects. (e.g. any BO can construct and save another BO within the same transaction, almost arbitrarily complex).

So, your DataPortal_Update() for your BO could look like this:

context = BeginTrans()

Collect changes in ChangesList

Write BO to database: BO.Update(context);

Write ChangesList to database: ChangesList.Update(context);

context.CommitTrans()

This is just for illustration. I actually do something very similar to this in my auditing implementation, except I don't collect my changes on a list -- that's overhead since I'm already server side. I call Update(context) on each one directly as it is created. 

In any case, you can see how you can similarly do whatever you want in your DataPortal_Update method, and if you have wrapped it in some sort of transaction scoping, then it is basically an atomic operation. If anything goes wrong while you are saving, it all gets rolled back.

Copyright (c) Marimer LLC