Hi everyone, I have some code that runs but it appears to timeout because of the transactionscope surrounding it. Two questions.
1. Can i increase the timeout for that 1 dataportal call only?
2. My business logic is within the dataportal routine, where i retrieve objects, calculate some numbers etc and i add objects to the database. The whole process must complete, that is why i have the transactionscope tag on the dataportal_execute method. I dont really want the retrieves to be within the transaction, for performance reasons, so can i just put the save methods within a transaction?
e.g
Sub DataPortal_Execute()
' Do some retrieves and calculations here
' Create a tranaction
' DO SAVES HERE?
End Sub
Is this possible?
Yes, switch to Manual transactions on your DP_Execute() method, and then manually create your own TransactionScope object in the method, only around the parts you want protected.
That should solve both problems.
Rocky,
Thanks, sorry to be a pain though, but how do i switch to manually transactions? Do i simply leave out the transactionScope tag and then write the transaction code? That what you mean?
Sorry if that sounds stupid
You'll change the attribute to be TransactionScope.Manual and then write the transaction code that is required for the whatever database you are using.
I was going to try and post an example, but still can't get the color formatting correct in my browser.
Here is a sample of what is discussed in this post...
<Transactional(TransactionalTypes.Manual)> _
Protected Overrides Sub DataPortal_Execute()
Dim options As TransactionOptions = New TransactionOptions() With {.IsolationLevel = IsolationLevel.ReadCommitted, .Timeout = TimeSpan.FromMinutes(4)}
Using ts As New TransactionScope(TransactionScopeOption.Required, options)
Using cn As New SqlConnection(Database.ApplicationConnection)
cn.Open()
Execute(cn)
ts.Complete()
End Using
End Sub
how do i switch to manually transactions? Do i simply leave out the transactionScope tag and then write the transaction code?
Hi,
Manual transaction is achieved by either not decorating your DataPortal_Execute() function with the Transactional attribute or by decorating your function with the Transactional attribute but setting its value to manual as in: [Transactional(TransactionalTypes.Manual)]
once you have done any of the above you can then go ahead and do your transactions stuff just like you would do it anywhere else.
Also, I found that CSLA only look at the attribute on the DataPortal_X method.
I had tried having DataPortal_Update check something (like a config file) and if it was supposed to avoid transactions, to call another method like "UpdateWithoutTransactions", to which I applied the Manual transaction scope attribute, but CSLA doesn't walk up the calling stack to find the first transactionscope attribute, it just looks at the Dataportal_X method that instantiated everything.
Also, I found that CSLA only look at the attribute on the DataPortal_X method. That’s right, internally, when the DataPortal_XYZ is decorated with the transactional attribute that requires a transaction, the CSLA delegates the update code to a class called TransactionalDataPortal. Inside that class the update code looks like this: -------------------------------------- public DataPortalResult Update(object obj, DataPortalContext context) -------------------------------------- Note how the portal.Update(obj, context) call (the code that ends up calling your acutal implementation of your DataPortal_XYZ ) is sorunded by the using (TransactionScope tr = new TransactionScope()). So basically, anything running inside the DataPortal_XYZ will use the transaction scope.
{
DataPortalResult result;
using (TransactionScope tr = new TransactionScope())
{
var portal = new DataPortalSelector();
result = portal.Update(obj, context); // Calls your acutal implementation of your DataPortal_XYZ
tr.Complete();
}
return result;
}
Copyright (c) Marimer LLC