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.
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();
}
}