I’m currently trying to figure out an issue after some code refactoring where the DbConnectionFactory is returning a valid IDbConnection but in closed state.
I have a service class with my Get endpoint (SearchService). The ctor parameters are correctly injected when the service is called. One of these is a class that itself has an injected IDbConnectionFactory. (PriceManager)
The endpoint function makes a call into the object which in turn creates an IDbConnection to make some db calls. It is also IDisposible.
When I start the API in debug mode, I see PriceManager being instantiated (which is a bit strange as it’s not used anywhere else). When I then call the endpoint, I see the SearchService get instantiated with another PriceManager as I would expect.
The endpoint code runs fine, calls the PriceManager function, returns and I see the PriceManager.Dispose getting called (which closes the IDbConnection).
However, here’s where things go wrong. When I call that endpoint a second time, SearchService and PriceManager are instantiated again, but when the code runs calling PriceManager function, the DbConnectionFactory injected into it returns an IDbConnection that is closed, causing the query to throw an exception. Furthermore, the Dispose function of PriceManager gets called at a point before this. If I remove the dispose of the IDbConnection the query runs fine.
I’m confused as to what’s going on here and if there is something in how SS instantiates and disposes of services that I’m missing.
Here are some dummied down versions of the classes.
[ConnectionInfo(NamedConnection = OrmliteDatabaseSettings.ConnectionName)]
[HmacOrCredentialsAuthRequired]
public sealed class SearchService : Service {
public SearchService(IPricingManager pricingmanager) {
this.pricingManager = pricingmanager;
}
public object Get(SearchRequest request) {
return pricingManager.GetPricing(request);
}
}
public class PricingManager: IPricingManager {
private readonly IDbConnectionFactory dbConnectionFactory;
private readonly string connectionName = OrmliteDatabaseSettings.ConnectionName;
private IDbConnection db;
public PricingManager(IDbConnectionFactory dbFactory)
{
this.dbConnectionFactory = dbConnectionFactory;
}
public IDbConnection Db => db ?? (db = dbConnectionFactory.OpenDbConnection(connectionName));
public object GetPricing(SearchRequest request)
{
var items = Db.Select(Db.From<table>());
// do some processing
return items;
}
public void Dispose()
{
db?.Dispose();
}
}
The DbConnectionFactory is registered as a SingleInstance in IOC (using autofac) and PricingManager is registered per lifetimescope (new instance for every usage).