Friday, August 24, 2012

Ways to prevent connection/resource leaks - Part 2

You may use these techniques to handle any expensive resource leaks, not just for connection leaks. In Part 1, I am explaining how to fix resource leaks in simpler ways. In this article I am explaining how to fix resource leaks with structuremap and how the structuremap object creation machnism works in multithreaded environment. Structuremap scopes explained here. Also I am explaining evils of singleton object in a multi-threaded environment.

  1. Fix for heterogeneous application - 1

  2. a. If your application is partially/not dependent on ORM.
    b. If your application uses DI/IOC tools like structure map.
    c. If your application is single threaded.

    Solution


    The fact is that singleton objects created by structuremap for HttpContext scope are cached. To create singleton object use the following line of code in your structuremap registry.
    Code:
    For<SqlConnection>().HttpContextScoped().Use(new SqlConnection());
    
    Since it is cached, you can easily dispose it in the global.asax file's Application_EndRequest event by calling the following method.
    Code:
    ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();
    

  3. Fix for heterogeneous application - 2

  4. a. If your application is partially/not dependent on ORM.
    b. If your application uses DI/IOC tools like structure map.
    c. If your application is multi-threaded, but uses limited number of threads.

    Solution


    The following line in structuremap registry creates object for both thread scope and http context scope.
    Code:
    For<SqlConnection>().HybridHttpOrThreadLocalScoped().Use(new SqlConnection());
    

    It requires two operations. One is thread scope cleanup and the other is HttpContext scope cleanup.

    In structuremap, thread scoped singleton objects are not cached. The above line of code creates one singleton object for each thread. The thread scoped singleton objects must be disposed at your own cost. That means you must explicitly dispose at the end of every thread in your application. Such as

    Code:
    ObjectFactory.GetInstance<SqlConnection>().Dispose();
    

    Now, the HttpContext scoped objects can be disposed by calling the following method in Application_EndRequest event.

    Code:
    ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();
    

  5. Fix for heterogeneous application - 3

  6. a. If your application is partially/not dependent on ORM.
    b. If your application uses DI/IOC tools like structure map.
    c. If you are restoring HttpContext.Current within the thread. That is, within a thread you cannot access HttpContext variables, it will be null. But in some cases you may need HttpContext data within a thread and you pass HttpContext.Current as parameter to the thread. This way you restore the HttpContext within a thread. Such as
    Code:
    //Thread method, this method will be executed in parallel by more than 1 threads. ThreadParameters is a class created by me.
    private void BindDataThread(ThreadParameters parameter)
    {
     //I need to access data from HttpContext, restoring it.
     HttpContext.Current = parameter.CurrentHttpContext;
     var connection = ObjectFactory.GetInstance<SqlConnection>();
    }
    

    If you use the above line, it will create a singleton object for HttpContextScope and the same object will be served for various threads from structuremap. Since SqlConnection object is not thread safe it will throw random errors. That means, all threads will be using the same SqlConnection object, one thread will be in retrieving data from the database and the other will be in opening the connection, the third one will be in closing the connection by using the same connection object.

    So what happens to the thread local scope? That I mentioned “HybridHttpOrThreadLocalScoped” in the structuremap registry to create object for thread local scope. Well, in structuremap the HttpContext scope takes precedence by checking HttpContext.Current != null. As soon as you assign "HttpContext.Current = parameter.HttpContext", it will only create object for HttpContext scope within a thread; but it supposed to create object for thread local scope!!

    So what can be the solution?

    Code:
    //For().HybridHttpOrThreadLocalScoped().Use(new SqlConnection());
    For<IVehicle>().LifecycleIs(new ThreadLocalStorageLifecycle()).Use<Car>();
    

    You may try by using the second option (the uncommented) instead of the first option (the commented) as I mentioned above.

    How it will work?

    This creates a singleton object for each thread. That is, the structuremap creates objects per thread basis, no matter for which context the object is requested.

    On the other hand, it can be overhead. Objects created in the page handlers/controllers are run by main thread. We have to dispose them too.

    We can use HttpModules or Application_EndRequest to dispose objects created in main thread.

    Otherwise, if we have an option in DI/IOC container to specify to take ThreadLocalScope lifecyle as precedence, it can be bit more easier.

    Note: If you are using nested DataReader this approach will not work. See the code below

    Code:
    
    int departmentCode;
    //The following statement opens an SqlConnection and going to be active throughout the scope of "using" statement.
    using (SqlDataReader departmentReader = GetDepartmentReader()) 
    {
     while (departmentReader.Read())
     {
      departmentCode = Convert.ToInt32(departmentReader.GetValue(0));
      //The following line will try to use an another reader in the same thread, Since we made the SqlConnection as singlton per thread, this code will again open the same connection and will throw error.
      using (SqlDataReader employeeReader = GetEmployeeReader(departmentCode))
      {
       ...
       ...
      }
     }
    }
    

    All this approaches may raise following questions in your mind.

  7. Why can't you use transient objects?
  8. Transient objects are not cached anywhere in structuremap, you can’t reference back and dispose them.

  9. Why can’t you use nested containers?
  10. For the situations that we discussed so far, I feel the nested containers are overhead. I can simply use “using” statement instead. Both provides the similar solution.


Back to Part-1

Monday, August 20, 2012

Ways to prevent connection/resource leaks - Part 1

You may use these techniques to handle any expensive resource leaks, not just for connection leaks. In Part 2, I am explaining how to fix resource leaks with structuremap. Also I am explaining evils of singleton object in a multi-threaded environment.

Preface:
This article describes ways to prevent connection leaks (i.e. SqlConnection leaks) when using DataReader.

In case of dataset you don’t have to open connection explicitly, to retreive data, the dataset automatically opens and closes the connection even if the connection's current state is closed. In most of the situation we tend to have our own application specific wrapper/API class for ADO.Net operations. Since dataset follows disconnected architecture, the connection can be easily closed in the wrapper/API class’s method itself. The problem lies in DataReader, here I am explaining two simple ways to prevent resource leaks for those situations

  1. Fix for classic application


  2. a. If your application is not using ORM like NHibernate.
    b. If your application is not using DI/IOC tool like StructureMap.

    Solution 1 - Traditional way


    Use “using” statement to dispose connection/DataReader objects.
    Code:
    
    protected void PrintData()
    { 
        string connString = "Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Northwind;";
        using (SqlConnection conn = new SqlConnection(connString))
        {
            SqlCommand cmd = conn.CreateCommand();
            cmd.CommandText = "SELECT ID, Name FROM Customers";
    
            conn.Open();
    
            using (SqlDataReader dr = cmd.ExecuteReader())
            {
                while (dr.Read())
                Console.WriteLine("{0}\t{1}", dr.GetString(0), dr.GetString(1));
            }//DataReader will be disposed
        } //Connection object will be disposed
    }
    

    Note:
    Avoid try/catch/finally block to dispose your object, I feel “using” makes my code much cleaner. "using” also disposes the object in the case of exception.

    Solution 2 – Disposing at Application_EndRequest


    This solution will be optimal when
    a.If you are using a wrapper class to operate objects
    b.If your application is very old and missed to close the connection in many places. The refactor may take long time, here is the quick solution.
    Code:
    //Cache the connection object in the wrapper/API when they are getting created
    public void CacheConnectionObject(SqlConnection connection)
    { 
        if (HttpContext.Current != null)
        {
            lock (_ConnectionSyncLock_) //Ensuring thread safe
            {
                IList<SqlConnection> connectionList;
                if (HttpContext.Current.Items[StringConstantKeys.SqlConnections] == null)
                {
                    connectionList = new List<SqlConnection>();
                }
                else
                {
                    connectionList = (IList<SqlConnection>)HttpContext.Current.Items[StringConstantKeys.SqlConnections];
                }
    
                connectionList.Add(connection);
                HttpContext.Current.Items[StringConstantKeys.SqlConnections] = connectionList;
            }
        }
    }
    
    Code:
    //Call this method in the Application_EndRequest event
    public void CloseSqlConnectionObjects()
    {    
        lock (_ConnectionSyncLock_) //Ensuring thread safe
        {
            if (HttpContext.Current != null && HttpContext.Current.Items[StringConstantKeys.SqlConnections] != null)
            {
                foreach (SqlConnection connection in (IList<SqlConnection>)HttpContext.Current.Items[StringConstantKeys.SqlConnections])
                {
                    try
                    {
                        if (connection != null)
                        {
                            if (connection.State != ConnectionState.Closed)
                            {
                                connection.Close();
                                //connection.Dispose(); I am not disposing it, since connection pool may reuse the same connection object across the HttpContext.
                            }
                        }
                    }
                    catch//Intentionally suppressing the errors, because this method called at the end of the request.
                    { }
                }
            }
        }
    }
    

  3. Fix for the enterprise application
  4. If your application is fully dependent on ORM

    Solution


    You don’t have to dispose anything related to connection object. Generally the ORM softwares are well designed to handle connection leaks. In case of NHibernate, it operates database in the context of NHibernate Session. Once the operation is over, it disposes the NHibernate Session as well as the objects associated with it.


Next-Part-2