Tuesday, July 31, 2007

Enable MARS on your NHibernate connection if you have SQL Server 2005

If you don't enable MARS, you'll get exceptions like these every now and then under high load:

Exception: There is already an open DataReader associated with this Command which must be closed first.
Stack Trace:
at System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command)
at System.Data.SqlClient.SqlConnection.ValidateConnectionForExecute(String method, SqlCommand command)
at System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader()
at NHibernate.Impl.BatcherImpl.ExecuteReader(IDbCommand cmd)
at NHibernate.Loader.Loader.GetResultSet(IDbCommand st, RowSelection selection, ISessionImplementor session)
at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
at NHibernate.Loader.Loader.LoadCollection(ISessionImplementor session, Object id, IType type)

To enable MARS, just add this on to our connection string:

MultipleActiveResultSets=true

Tuesday, July 10, 2007

MonoRail Exception Chaining

MonoRail comes with a nice exception handling mechanism. It's pretty well documented so I won't explain how it works.

MonoRail also provides an handler that sends an email with exception and request details. I got tired of getting this email in my development environment, so here's what I came up with:

    public class ExceptionFilterHandler : AbstractExceptionHandler

    {

        public override void Process(IRailsEngineContext context)

        {

            if (context.Request.IsLocal)

                return;

 

            InvokeNext(context);

        }

    }



Pretty simple and it does the trick. This also gives you the ability login to the server in production if you have access and see the exception detail in the browser instead of getting an email. It checks to see the web request was made from the local machine.

Disregard the previous post

For some reason, the code I posted below doesn't work anymore. I don't have the time to see what changed. Hopefully soon I'll get a chance to revisit it and see what happened to MicroKernel that made the code stop working.