I am about using ObjectDataSource on a Page to display and update DO4 entities. This means that the datasource and the gridview etc. will read the entities directly, so a transaction should be running there. I am new to ASP.NET. What is the best places for transaction boundaries? Is it good to have only one transaction during a request? Say I put Transaction.Open() into Page_Load, and put TransactionScope.Dispose() into Page_PreRenderComplete (which is after datasource refreshing). But where to put transactionScope.Complete()? Page_PreRenderComplete will run anyway, so I cannot put it there. It can happen that the business logic fails -- so the transaction is aborted --, but my page should show up and refresh the datasources. So what is the best way to go? How do you do it?

Thanks


Updated at 29.01.2010 14:00:59

Thanks for the quick response Alex.

"- Moreover, new transaction will be already created there. It will be committed on successful completion of request, otherwise it will be rolled back."

Do you mean here that some unhandled exception happens, and the page is not created successfully?

"- Setting SessionManager.Demand().Error to true will lead to rollback of this transaction as well."

Does this mean that if a business exception thrown in a business process is catched then this property should be set to true in all cases, otherwise the transaction will be committed with the wrong data? If the transaction is aborted somewhy, then data sources won't be able to fill the controls? Or is the transaction aborted only at the end of the request (by not calling transactionScope.Complete())?

Thanks

This thread was imported from our support forum. The original discussion may contain more detailed answer. Original topic by otto.

asked Jan 28 '10 at 22:18

Editor's gravatar image

Editor
46154156157


One Answer:

We developed SessionManager (IHttpModule) to handle this task. To use it, you should enable it in Web.config (see the one of of ASP.NET sample) and use its DomainBuilder event (normally - in Global.asax.cs).

SessionManager ensures the following:

  • When Session.Current is accessed, and there is no current Session, it will provide one

  • Moreover, new transaction will be already created there. It will be committed on successful completion of request, otherwise it will be rolled back.

  • Setting SessionManager.Demand().Error to true will lead to rollback of this transaction as well.

  • SessionManager.Current (and SessionManager.Demand()) returns the instance of SessionManager bound to the current HttpContext, i.e. current SessionManager. Its Session property (if not null) is the same value as the one provided by Session.Current.

Note that presence of SessionManager does not prevent you from creating Sessions manually: it operates relying on Session.Resolver event, which is raised only when there is no current Session. So if you create a SessionManually, no automatic Session ( + transaction) will be provided.

Finally, no automatic Session + transaction will be provided, if you don't use Session.Current \ Session.Demand() methods in your code (directly or indirectly). So e.g. requests to static web pages won't lead to any DB interaction.

You also should know that getting automatically provided Session (Session.Current, which is resolved via Session.Resolver, which is ~ SessionManager.Current.Session) is relatively slow operation: its speed is nearly equal to the speed of getting HttpContext.Current. "Normal" Session.Current is ~ 10+ times faster (if you're interested, we can measure this). So if there is a place where it is frequently used, you can use session activation to avoid this:

using (Session.Demand().Activate()) {
  // Session.Current here does not rely on Session.Resolver any more
}

Since nearly the same code is injected by our TransactionalAspect to any public method of any SessionBound descendant by default, the code running there does not need anything like this.


First question: transaction is rolled back if HttpApplication.Error event is raised. Its handler attached by SessionManager just sets its HasErrors property to true.

Second question: yes, except the case covered by first question :)

answered Jan 29 '10 at 06:32

Alex%20Yakunin's gravatar image

Alex Yakunin
29714412

Your answer
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!
toggle preview

Subscription:

Once you sign in you will be able to subscribe for any updates here

Tags:

×574

Asked: Jan 28 '10 at 22:18

Seen: 3,905 times

Last updated: Jan 28 '10 at 22:18

powered by OSQA