Results 1 to 5 of 5

Thread: OpenSessionInView and FlushMode

  1. #1
    Join Date
    Apr 2011
    Posts
    57

    Default OpenSessionInView and FlushMode

    Hello all,

    From a bit of googling I get the impression that when the OpenSessionInView module opens the Nhibernate session it sets the flush mode to 'Never'. Is this true or have I made a mistake?

    If it is true:

    1) Why? This seems unnecessary to me. We have the 'ReadOnly' attribute on transactions to tell Nhibernate to not flush the session when committing the transaction.

    2) How do I change this default behaviour? , ie can I override this setting? I want transactions that are not marked as 'readonly' to automatically flush the session when they commit, which is the standard Nhibernate behaviour if the flush mode is set to 'Auto' or 'Commit'.

    many thanks,
    Jordan.

  2. #2
    Join Date
    Apr 2011
    Posts
    57

    Default

    Ok - I was mislead. OpenSessionInViewFilter doesn't set the FlushMode to Never. It seems in my app that the FlushMode is 'Auto'.

    However, I would still like to set the FlushMode to 'Commit'. Is there any way of doing this if I am not using the HibernateTemplate in my daos?

    Would I have to hack or inherit from the OpenSessionInViewFilter to make it set the FlushMode to 'Commit' when it creates the session?

    thanks again,
    Jordan

  3. #3
    Join Date
    Oct 2006
    Location
    Bergen, Norway
    Posts
    365

    Default

    Hi!

    You could do something like this:
    Code:
        /// <summary>
        /// The SessionScopeGuard will guard the session and close
        /// it when the guard is disposed.
        /// </summary>
        public class SessionScopeGuard : IDisposable
        {
            private static readonly ILog log = LogManager.GetLogger(typeof(SessionScopeGuard));
            private SessionScope scope;
        	private bool transactional;
        	private ISessionFactory sessionFactory;
    
        	/// <summary>
            /// Read-only scope.
            /// </summary>
            public SessionScopeGuard(ISessionFactory sessionFactory)
            {
                this.sessionFactory = sessionFactory
                transactional = false;
                scope = new SessionScope(sessionFactory, false);
                scope.Open();
            }
    
            /// <summary>
            /// Transactional scope.
            /// </summary>
        	public SessionScopeGuard(ISessionFactory sessionFactory, bool transactional)
        	{
                this.sessionFactory = sessionFactory
                this.transactional = transactional;
                scope = new SessionScope(sessionFactory, false);
                scope.Open();
                // So far, we have a read only session, that means the FlushMode is Never. 
                // If we expect one or more transactions to take place while this session is open,
                // then we must change the FlushMode to Auto. This is what the transactional block
                // below does:
                if (transactional)
                {
                    ISession session = SessionFactoryUtils.GetSession(sf, false);
                    // Modifying default FlushMode from ReadOnly to Auto:
                    session.FlushMode = FlushMode.Auto;
                }
        	}
    
            /// <summary>
            /// Exposes the session created by the guard...
            /// </summary>
            /// <returns></returns>
            public ISession GetSession()
            {
                ISession session = null;
                try
                {
                    session = SessionFactoryUtils.GetSession(sessionFactory, false);
                    if (transactional) session.FlushMode = FlushMode.Auto;
                }
                catch (InvalidOperationException ioe)
                {
                    if (log.IsDebugEnabled)
                    {
                        log.Debug("Failed to flush the session. Reason could be that the session has somehow already been closed.", ioe.GetBaseException());
                    }
                    session = sessionFactory.OpenSession();
                    if (transactional) session.FlushMode = FlushMode.Auto;
                }
                catch (Exception e)
                {
                    if (log.IsDebugEnabled)
                    {
                        log.Debug("Failed to flush the session. Not sure what to do here, check exception: [" + e.Message + "]", e);
                    }
                }
                return session;
            }
    
        	/// <summary>
            /// Dispose the open session.
            /// </summary>
            public void Dispose()
        	{
                if (transactional) Flush();
        	    try
        	    {
        	        scope.Close();
                    scope.Dispose();
        	    }
        	    catch (Exception e)
        	    {
                    if (log.IsDebugEnabled) log.Debug("Failed to close the session scope. Extract session and flush it if it is not null!", e);
                    ISession session = SessionFactoryUtils.GetSession(sessionFactory, false);
                    if(session != null)
                    {
                        if(session.FlushMode == FlushMode.Auto) session.Flush();
                        session.Close();
                    }
                }
        	}
    
            /// <summary>
            /// Flushing and commiting data in transaction without closing the connection. Method can only be called manually.
            /// </summary>
            public void Flush()
            {
                ISession session = GetSession();
                if (session != null && transactional)
                {
                    session.Flush();
                    session.Clear();
                }
            }
        }
    Cheers,
    Steinar.

  4. #4
    Join Date
    Apr 2011
    Posts
    57

    Default

    Hi,

    Thanks for that.

    But I've actually decided that the standard set up with OpenSessionInViewFilter and Transactions works well for me. (I hadn't set up the transaction management properly before - oops).

    regards,
    Jordan.

  5. #5
    Join Date
    Oct 2006
    Location
    Bergen, Norway
    Posts
    365

    Default

    Hi!

    I usually just use the transaction driven way myself. But I have been in situations where I wanted to have a session span multiple transactions and then Spring.Net's SessionScope is a nice class to use, wrapped in a guard as above, this can be used in an advice as well. Just search for the SessionScopeAdvice on the forums and I'm sure you'll find the code.

    Glad you got it working,
    Steinar.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •