StrataFrame Forum

Further Weirdness with DB2 Transactional Save

http://forum.strataframe.net/Topic12292.aspx

By PeterA - 10/30/2007

I don't know how I do it, but I think I can find the strangest bugs and always at the last minute. Smile



I had everything built and had completed my QA testing. Everything functioned great, the BrokenRule issue was resolved. So, I moved all my files into the staging area. It's just a different directory on the same server, same hard drive. I set up a second QC/staging Web site and started clicking through to make sure permissions were all set up and working the way they did on the development site and I had some more issues.



As I said, this is on the same server and the same hard drive, just a different file path. I made sure all my config values were updated to use the new path for logging and database login information (still connects to the same database, but accesses a file in a different path location). It logs in, gets me data and works fine. When I try to save something, for example, modified application permissions for a role, it blows up.



I finally tracked it down to it claiming the transaction key didn't exist. I double checked and it starts the transaction. I added some code to conditionally use the transaction if it exists. So I check the Transactions collection for the key and if it exists, I tell the business object to save using the transaction. If it doesn't, I have it save without a transaction. It detects that there is a transaction and then throws an exception that the key does not exist. Here's the stack trace:



at MicroFour.StrataFrame.Business.BusinessLayer.Save(Boolean Transactional, String TransactionKey)

at Payless.Sourcing.MaterialsManagement.Admin.Permissions.cmdSave_Click(Object sender, ImageClickEventArgs e) in I:\PSS Design\Visual Studio\Materials Management\MM_UI\Administration\permissions.aspx.cs:line 218




And here's the Exception and Inner Exception that get thrown:



EXCEPTION: An error occurred while saving the data to the server.

INNER EXCEPTION: Save cannot continue because a transaction with the key [PermissionsUpdate] has not been started.




I'm thoroughly confused about this one since it all works fine and lets me save in the development area, but not in the QC area. They reference the same Strataframe assemblies and the same IBM.Data.DB2 assembly. It was just a straight copy of the files from one directory (D:\Dev\Application\) to another (D:\QC\Application).



Any ideas what could be causing this?



Thanks!
By PeterA - 10/30/2007

Well, I discovered I'd made one difference in the config file. Sorry, I thought everything was the same, but it's still a little strange.



The Dev version didn't have a DataSourceKey specified and the QC version did. Basically, this is just a value that I use throughout the application as the key to my datasource. I initialize all the business objects to use it when the application is started and I reference it as my connection as well. Why would it have a problem when a DataSourceKey is specified to something other than an empty string and not with an empty string?



Thanks!
By PeterA - 11/1/2007

Just wanted to know if there'd been any progress on confirming the problem. This particular bug makes it impossible for me to connect to multiple databases from one application.



Thanks!



Peter
By StrataFrame Team - 11/5/2007

You say that you initialize the DataSourceKey on the business objects from the value in the config file... How are you initializing it?  Are you just setting the value in the constructor, or some other way?  Most likely, it seems that the transaction is being started on the wrong data source (say the tran is getting started for data source "", while the business object is expecting it to be started for data source "MyDataSource").  Check the place where you call TransactionBegin() and make sure that you're using the data source key from your config file to start the transaction.
By PeterA - 11/5/2007

Ben Chase (11/05/2007)
You say that you initialize the DataSourceKey on the business objects from the value in the config file... How are you initializing it? Are you just setting the value in the constructor, or some other way?




I have a method in the Global.asax file that I call during the Page_Init event. It takes a parameter of type ApplicationBasePage (pass in "this" as the parameter value) and set the data source keys on all the objects that way.



Ben Chase (11/05/2007)
Most likely, it seems that the transaction is being started on the wrong data source (say the tran is getting started for data source "", while the business object is expecting it to be started for data source "MyDataSource"). Check the place where you call TransactionBegin() and make sure that you're using the data source key from your config file to start the transaction.




That was what I started to think might be the problem, but I've only got one data source object that I'm using. Also during Page_Init I assign a value of type Db2DataSourceItem to a page-level object attribute (mySqlh). I call the TransactionBegin off this object. It's worked fine on all my other pages (starting the transaction on the same page-level object attribute), it's only on this one page that I seem to be having a problem. It's very strange.



Here's the code where I start it:





// Start the transaction

if (!mySqlh.Transactions.ContainsKey("PermissionsUpdate"))

{

SqlHandler.Tracer.LogMessage("Starting transaction: PermissionsUpdate", TraceLevel.Verbose);

mySqlh.TransactionBegin("PermissionsUpdate", IsolationLevel.ReadUncommitted);

}





I don't think there's much I can really screw up on it and I've used this same method all through my application. As I said, it's just on this one page.



Thanks!
By StrataFrame Team - 11/6/2007

Aha, that's the problem... the transaction is owned by the data source... it's not static.  So, the transaction has to be started on the data source that is being used by the business object, not just on any data source.  There are wrapper methods on the BusinessLayer class that can start the transactions, so you might try to use one of those:

BusinessLayer.TransactionBegin(this.someBo.DataSourceKey, "TranKey");

By PeterA - 11/7/2007

Ben Chase (11/06/2007)
Aha, that's the problem... the transaction is owned by the data source... it's not static. So, the transaction has to be started on the data source that is being used by the business object, not just on any data source. There are wrapper methods on the BusinessLayer class that can start the transactions, so you might try to use one of those:



BusinessLayer.TransactionBegin(this.someBo.DataSourceKey, "TranKey");




I changed the code to look like this:





// Start the transaction

if (!DataLayer.DataSources[Authorization.DataSourceKey].Transactions.ContainsKey("PermissionsUpdate"))

{

SqlHandler.Tracer.LogMessage("Starting transaction: PermissionsUpdate", TraceLevel.Verbose);

BusinessLayer.TransactionBegin(Authorization.DataSourceKey, IsolationLevel.ReadUncommitted);

}





It corrected the problem. I believe I understand why, now. Essentially, because I had put the connection into it's own container (the mySqlh property), the transaction starts/stops I called there really didn't have an effect on the DataLayer the business objects used. Does that about sum it up?



Thanks!
By StrataFrame Team - 11/7/2007

Yep, that about sums it up Smile

Glad you got it working.

By PeterA - 11/7/2007

Ben Chase (11/07/2007)
Yep, that about sums it up Smile



Glad you got it working.




Me, too. Smile



New question, now (though related in a very roundabout way). Smile What events are fired off when you create a business object on the fly (i.e. in the background when its going to be filled and used to populate a DropDownList)?
By PeterA - 11/7/2007

I should probably qualify that question. What events are fired off on the business object when it's created in the background? Smile I realized there were a couple different ways to answer that right after I clicked "Post". :-).
By Trent L. Taylor - 11/7/2007

When it is created, it is just going to fire the normal component events.  The only custom event that gets fired at creation time is the ParentFormLoading which will not fire if it is created in code.  The events related to the BO are going to be once the object is created.  I am not very clear on your question so I don't know if that is what you were looking for or not. Ermm
By PeterA - 11/8/2007

Trent L. Taylor (11/07/2007)
When it is created, it is just going to fire the normal component events. The only custom event that gets fired at creation time is the ParentFormLoading which will not fire if it is created in code. The events related to the BO are going to be once the object is created. I am not very clear on your question so I don't know if that is what you were looking for or not. Ermm




That answers my question. I was after whether ParentFormLoading fired when it was created in the background. I just had a cryptic way of getting there. BigGrin



Thanks!
By Trent L. Taylor - 11/8/2007

Good deal Smile