Thanks for the replies, really helpful.
I'd just like to clarify a couple of final points based on the feedback:
- Should I be doing a session.flush() and then a session.dispose() on
EndRequest/Error, or is dispose enough?
- On my begin/end request I'm also starting a Transaction. Is this
recommended? I tried it without an overall Transaction but got some weird
results (deleted objects showing up again on my page etc), is this expected?
Thanks,
Paul
On Friday, 22 June 2012 18:27:26 UTC+1, Ricardo Peres wrote:
>
> Also don't forget to dispose the session, both on EndRequest as well as on
> Error (if an unhandled exception occurs, the EndRequest event will not be
> raised).
>
> On Friday, June 22, 2012 5:31:02 PM UTC+1, Jason Meckley wrote:
>>
>> session per request is the way to go. instead of holding the session in
>> an Ioc place it in the request's context.
>>
>> Transactions are a bit trickier with webforms. When using a client (code)
>> side POID like hilo or guid NH doesn't actually issue any sql queries to
>> the DB until the transaction is committed. this is in alignment with the
>> concepts of a UoW. If a db generated id like identity is used, then NH must
>> hit the DB as soon as you call Save or Delete to keep the object graph in
>> sync with the database.
>>
>> With MVC reads/GETS and writes/POSTs can be separated into unique
>> requests using the Post/Redirect/Get workflow. This doesn't exist in
>> Webforms because both commands and queries are issued in the postback.
>>
>> So for transactions in webforms I like to create a simple Transaction
>> wrapper extension method to encapsulate the
>> begin/try-commit/catch-rollback/finally - dispose code.
>>
>> On Friday, June 22, 2012 11:31:33 AM UTC-4, Paolo wrote:
>>>
>>> Hi all,
>>>
>>> I've been trying to come up with/find a 'best practice' route for NHib
>>> session management in ASP.Net WebForms. I'm unable to use IoC containers
>>> etc due to architectural features of the code (it's a fixed framework we
>>> use internally). What I'm looking for is some pointers on the solution
>>> I've come up with, as I'm sure it could be improved.
>>>
>>> Keeping it simple, I'm trying to achieve session-per-request with no
>>> requirement for transactions. The code below has an overall 'wrapping'
>>> transaction because I found if I did a delete then immediately re-loaded
>>> the list objects to the page in the same cycle, the deleted object would
>>> 're-appear', even though I'd just deleted it (object disappears if I do a
>>> page refresh). Not entirely sure why this is if I'm honest! Do I need a
>>> Transaction/is it best practice?
>>>
>>> Overall code is (the extension stuff is because I'm using IIS6 and found
>>> it begins/ends even when loading images etc):
>>>
>>> protected void Application_BeginRequest(object sender, EventArgs
>>> args)
>>> {
>>> HttpContext context = this.Context;
>>> string filePath = context.Request.FilePath;
>>> string fileExtension =
>>> VirtualPathUtility.GetExtension(filePath);
>>> if (fileExtension.Equals(".aspx") ||
>>> fileExtension.Equals(".ashx"))
>>> {
>>> SessionFactoryManager.Instance.BeginTransaction();
>>> }
>>> }
>>>
>>> protected void Application_EndRequest(object sender, EventArgs
>>> args)
>>> {
>>> HttpContext context = this.Context;
>>> string filePath = context.Request.FilePath;
>>> string fileExtension =
>>> VirtualPathUtility.GetExtension(filePath);
>>> if (fileExtension.Equals(".aspx") ||
>>> fileExtension.Equals(".ashx"))
>>> {
>>> SessionFactoryManager.Instance.CommitTransaction();
>>> SessionFactoryManager.Instance.CloseSession();
>>> }
>>> }
>>>
>>> The session manager is a singleton and the interesting bits are:
>>>
>>> public ISession GetSession()
>>> {
>>> ISession session = ContextSession;
>>>
>>> if (session == null)
>>> {
>>> session = sessionFactory.OpenSession();
>>> session.FlushMode = FlushMode.Commit;
>>>
>>> ContextSession = session;
>>> }
>>>
>>> //Check.Ensure(session != null, "session was null");
>>>
>>> return session;
>>> }
>>>
>>> public void BeginTransaction()
>>> {
>>> ITransaction transaction = ContextTransaction;
>>>
>>> if (transaction == null)
>>> {
>>> transaction = GetSession().BeginTransaction();
>>> ContextTransaction = transaction;
>>> }
>>> }
>>>
>>> public void CommitTransaction()
>>> {
>>> ITransaction transaction = ContextTransaction;
>>>
>>> try
>>> {
>>> if (HasOpenTransaction())
>>> {
>>> transaction.Commit();
>>> ContextTransaction = null;
>>> }
>>> }
>>> catch (HibernateException)
>>> {
>>> RollbackTransaction();
>>> throw;
>>> }
>>> }
>>>
>>> /// <summary>
>>> /// If within a web context, this uses <see cref="HttpContext"
>>> /> instead of the WinForms
>>> /// specific <see cref="CallContext" />. Discussion concerning
>>> this found at
>>> /// http://forum.springframework.net/showthread.php?t=572.
>>> /// </summary>
>>> private ITransaction ContextTransaction
>>> {
>>> get
>>> {
>>> if (IsInWebContext())
>>> {
>>> return
>>> (ITransaction)HttpContext.Current.Items[TRANSACTION_KEY];
>>> }
>>> else
>>> {
>>> return
>>> (ITransaction)CallContext.GetData(TRANSACTION_KEY);
>>> }
>>> }
>>> set
>>> {
>>> if (IsInWebContext())
>>> {
>>> HttpContext.Current.Items[TRANSACTION_KEY] = value;
>>> }
>>> else
>>> {
>>> CallContext.SetData(TRANSACTION_KEY, value);
>>> }
>>> }
>>> }
>>>
>>> /// <summary>
>>> /// If within a web context, this uses <see cref="HttpContext"
>>> /> instead of the WinForms
>>> /// specific <see cref="CallContext" />. Discussion concerning
>>> this found at
>>> /// http://forum.springframework.net/showthread.php?t=572.
>>> /// </summary>
>>> private ISession ContextSession
>>> {
>>> get
>>> {
>>> if (IsInWebContext())
>>> {
>>> return
>>> (ISession)HttpContext.Current.Items[SESSION_KEY];
>>> }
>>> else
>>> {
>>> return (ISession)CallContext.GetData(SESSION_KEY);
>>> }
>>> }
>>> set
>>> {
>>> if (IsInWebContext())
>>> {
>>> HttpContext.Current.Items[SESSION_KEY] = value;
>>> }
>>> else
>>> {
>>> CallContext.SetData(SESSION_KEY, value);
>>> }
>>> }
>>> }
>>>
>>> private bool IsInWebContext()
>>> {
>>> return HttpContext.Current != null;
>>> }
>>>
>>> Thanks for any thoughts on the above, as I've been finding it really
>>> hard to track down current information regarding NHibernate and WebForms
>>> without the use of IoC frameworks to manage sessions, etc.
>>>
>>> Thanks,
>>>
>>> Paul
>>>
>>
--
You received this message because you are subscribed to the Google Groups
"nhusers" group.
To view this discussion on the web visit
https://groups.google.com/d/msg/nhusers/-/jHRArFqHdjAJ.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/nhusers?hl=en.