Using the "per-request" approach with StructureMap and IDbConnection - the connection is opened but is closed when executed

dapper structuremap

Question

Trying to set up Dapper with StructureMap to utilize a "per request" type of scenario. In my Global.asax I have the following (modified from an old post of Ayende's involving NHibernate, and one I found discussing the BuildUp() method in StructureMap):

protected static IDbConnection CreateConnection() { 
    var settings = ConfigurationManager.ConnectionStrings["MyConnectionString"];
    var connection = DbProviderFactories.GetFactory(settings.ProviderName).CreateConnection();
    if (connection == null) { 
        throw new ArgumentNullException("connection");
    }
    connection.ConnectionString = settings.ConnectionString;
    return connection;
}

public static IDbConnection CurrentConnection { 
    get { return (IDbConnection)HttpContext.Current.Items["current.connection"]; }
    set { HttpContext.Current.Items["current.connection"] = value; }
}

public Global() { 
    BeginRequest += (sender, args) => { 
        CurrentConnection = CreateConnection();
        CurrentConnection.Open(); 
    };

    EndRequest += (sender, args) => { 
        if (CurrentConnection == null) return;
        CurrentConnection.Close();
        CurrentConnection.Dispose();
    }
}

void Application_Start(object sender, EventArgs e) { 
    ObjectFactory.Initialize(x => { 
        x.For<IDbConnection>().Singleton().Use(CreateConnection());
        x.For<ICustomerRepository>().Use<CustomerRepository>();
        x.SetAllProperties(y => y.OfType<ICustomerRepository>());
    });
}

// BasePage.cs
public class BasePage : System.Web.UI.Page { 
    public IDbConnection CurrentConnection { get; set; }

    public BasePage() { 
        ObjectFactory.BuildUp(this);
    }
}

Every time I try to call this, the actual query fails with an error stating the Connection's current state is closed, although a breakpoint on the BeginRequest handler shows that Open() is being called on the connection.

It seems to work if I manually call Open and Close on the IDbConnection inside each repository method, but I'm trying to avoid having to do that if at all possible.

Accepted Answer

You're creating the connection as a singleton. That means that there will only be one connection object used for the entire applications pages. The connection that you new up in the Application_Start handler is never used by the pages, since they will get the connection from the container.

You would be better off using something like this:

void Application_Start(object sender, EventArgs e) { 
    ObjectFactory.Initialize(x => { 
        x.For<IDbConnection>().HttpContextScoped().Use(() => CreateConnection());
        ...
    }
}

 public Global() { 
    EndRequest += (sender, args) => { 
        ObjectFactory.GetInstance<IDbConnection>.Dispose();
    }
 }



Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why