Don't flush the session after an exception occurs - NHibernate

后端 未结 3 1516
被撕碎了的回忆
被撕碎了的回忆 2021-01-05 01:02

I am developing a ASP.NET MVC web app under .NET 3.5, NHibernate and hosted on Windows Azure. When, the webapp is run from the local development fabric it works fine. Yet, w

相关标签:
3条回答
  • 2021-01-05 01:44

    You should never catch exceptions and ignore them during a NHibernate transaction.

    I try to explain why.

    There could be exceptions for instance caused by constraints in the database. (it could also be caused by mapping problems, exceptions thrown by properties or anything else.) NHibernate tries to synchronize the state in memory with the database. This is done on commit - and sometimes before queries to make sure that queries are done on actual data. When this synchronization fails, the state in the database is something random, some changes are persisted, others are not. The only thing you can do in such a case is closing the session.

    Consider that decisions and calculations in your code are based on values in memory. But - in case of an ignored exception, this values are not the values in the database, they will never be there. So your logic will decide and calculate on 'fantasy-data'.

    By the way, it is never a good idea to catch any exception (untyped) and ignore them. You should always know the exceptions you handle, and be sure that you can continue.

    What you're doing here is swallowing programming errors. Believe me, the system will not be more stable. The question is only: do you notice the error when it occurs, or do you ignore it there and even persist the result of the error to the database? When you do the latter, you don't have to be surprised when your database is inconsistent and other error arise when you try to get the data from the database. And you will never ever find the code that is the actual cause of the error.

    0 讨论(0)
  • 2021-01-05 01:52

    This exception can occur if your column names include reserved words (e.g. use status as a column name and it will become impossible to Save)

    0 讨论(0)
  • 2021-01-05 02:00

    I have finally found a solution to my own problem. In case people would be interested, I am posting the solution here.

    public class SimpleRoleProvider : RoleProvider 
    {
        // isolated session management for the RoleProvider to avoid
        // issues with automated management of session lifecycle.
    
        public override string[] GetRolesForUser(string username)
        {
            using (var session = GlobalSetup.SessionFactory.OpenSession())
            {
                var users = new UserRepository(session);
                var user = users.Get(username);
    
                // no role if user is not registered
                if (null == user) return new string[0];
    
                // default role for registered user
                return user.IsManager ? new[] {"Manager", "User"} : new[] {"User"};
            }
        }
    }
    

    Basically what was happening is that the RoleProvider repository does not seem to have the same lifecycle than regular in-view / in-controller repositories. As a result, at the time the RoleProvider is called, the NHibernate session has already been disposed causing the exception observed here above.

    I have replaced the code by the following one here above. This one has its own NHibernate session management, and ends up working fine.

    0 讨论(0)
提交回复
热议问题