Transaction Rollback and Update

Transaction Rollback and Update

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


Wbmstrmjb posted on Wednesday, December 03, 2008

We have concurrency checks built in to the database such that if two people get data and write back, the first one will save and the second person will get an error and the new data in the database is returned (ie if a record has a name of "Dave" and two people get that record and person 1 saves "Frank" in database and person 2 tries to save "Fred", person 2 will get an error and the screen will refresh the data to now show "Frank").

As part of the concurrency, the refresh needs to be done in the Update call (basically just a Fetch to get the current data).  If I do the Fetch with Transactional scope off, it works fine and no problems.  If I turn it on (such that any child concurrency issues refresh the object), it blows up with a "The instruction at 'XXXXX' referenced memory at 'XXXXX'. The memory could not be 'written'."  Does anyone know why this is happening?

Thanks,
Mike

ajj3085 replied on Wednesday, December 03, 2008

I can't answer your question... only state that I got a similar problem in my custom DAL, when my DAL was doing Reflection and using the Dynamic Method execution method (which is also used by Csla).  I never found out WHY it was happening... I ended up changing my DAL to not use dynamic methods and back to plain old methodinfo.  Unless I got rid of it in favor of Linq, anyway..

IIRC, it started happening after installing .Net 3.5.

rsbaker0 replied on Wednesday, December 03, 2008

I was wondering how you are returning the error to the user? Are you throwing an exception (this is what we do)? However, I don't see you how you get a refreshed object back across the data portal in this case (e.g. if CSLA had cloned your object before saving).

If you have a common base class between your BO and the CSLA classes, a possible workaround might be to throw your own "ConcurrencyViolation" type exception and catch it on the client side of the portal. Then you could display the error and refetch over the data portal and avoid the transaction scope problem.

Wbmstrmjb replied on Wednesday, December 03, 2008

We do have an exception being thrown and a base class that extends CSLA.  The Save method is overidden as follows:

         public override T Save()
        {
            // Read Only implementation
            if (_readOnly)
                throw new Exception("Cannot Save a ReadOnly object.");

            T obj = base.Save();

            if (_rowCount.Int == 0) // need to call fetch to refresh data and then throw error
                obj.Refresh();               

            return obj;
        }

_rowCount is a SmartInt (ie int) that is returned from SPs with how many records were affected.  Refresh is a virtual function that throws a Concurrency Error and when implemented calls Fetch for the object to refresh.  This is probably where the issue lies, though it works perfectly fine if TransactionalScope is not set.

Does this help?

rsbaker0 replied on Thursday, December 04, 2008

Yes, this helps.

The Save() method (and code you are showing) generally runs on the client side of the data portal -- CSLA implements it via DataPortal_Update, so what are you marking with TransactionScope? My thinking is that only the server side portions of the data portal execution code be marked with a scope (but I could be wrong).

Wbmstrmjb replied on Thursday, December 04, 2008

I did more testing and even without the Refresh, the Save is getting the error when TransactionalScope is set.  Not sure where it is happening now.

rsbaker0 replied on Thursday, December 04, 2008

Which method are you tagging with the TransactionScope attribute?

Wbmstrmjb replied on Thursday, December 04, 2008

Just the DataPortal_Update.

rsbaker0 replied on Thursday, December 04, 2008

Ouch. That's what I assumed but just wanted to be sure you weren't doing something weird.

It sounds like TransactionScope isn't working for you at all? or is it just having problems when a rollback has occurred?

Wbmstrmjb replied on Friday, December 05, 2008

Just a thought.  Does TransactionScope not work with Oracle in CSLA?

ajj3085 replied on Friday, December 05, 2008

It wouldn't have anything to do with Csla.  I would TS will work, but it may start up DTC to handle it.  So it may not work like you want it to.

Wbmstrmjb replied on Friday, December 05, 2008

I wrapped the call in a Transaction and it all worked correctly.  I wonder why the attribute isn't doing the same.  I thought Rocky had stated that it just did basically the same thing.

JoeFallon1 replied on Friday, December 05, 2008

Since we know that CSLA works correctly with transactions and the attribute, but it fails in your project, we have to conclude that there is a bug in your code or else your environment has a configuration problem. I suggest you post the entire BO code and describe your environment in more detail if you really want to resolve this.

Joe

 

tmg4340 replied on Friday, December 05, 2008

It does - but I'm guessing it's the Oracle interface that is causing you problems.  IIRC, getting Oracle to work with .NET's TransactionAttribute requires additional Oracle setup, and is only supported on certain versions of Oracle (I think 10g+, but that's a guess.)  And Oracle might rely on the DTC to do some of the heavy lifting (SQL Server has an internal implementation that promotes to DTC only when necessary), so you might have to look at setting that up as well.  Lastly, I'd check to see whether you have to use Oracle's .NET driver, or whether MS's version will work.

I am not an Oracle expert, but I know I have seen documentation concerning this before, both on the 'net and on this forum.  You might do a search here and see what you find.  But I'd bet that's your problem.

HTH

- Scott

Copyright (c) Marimer LLC