I'm using the Db
property in a ServiceStack service to access my database but every now and then I get the following error from IIS:
Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.
Stack Trace:
[InvalidOperationException: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.]
System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection) +6371713
System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory) +6372046
System.Data.SqlClient.SqlConnection.Open() +300
ServiceStack.OrmLite.OrmLiteConnection.Open() +44
ServiceStack.OrmLite.OrmLiteConnectionFactory.OpenDbConnection() +132
ServiceStack.ServiceInterface.Service.get_Db() +68
I have set the ReuseScope
in the Configure
method to ReuseScope.None
which should close the connection on a per request basis I believe? What am I doing wrong here?
public override void Configure(Container container)
{
JsConfig.EmitCamelCaseNames = true;
//Register all your dependencies
ConfigureDb(container);
//Set MVC to use the same Funq IOC as ServiceStack
ControllerBuilder.Current.SetControllerFactory(new FunqControllerFactory(container));
}
ConfigureDb:
private static void ConfigureDb(Container container)
{
var connectionString = ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString;
container.Register<IDbConnectionFactory>(c =>
new OrmLiteConnectionFactory(connectionString, SqlServerDialect.Provider))
.ReusedWithin(ReuseScope.None);
using (var db = container.Resolve<IDbConnectionFactory>().Open())
{
// Do database seed/initialisation
}
}
Edit
After more diagnosis, it seems to happen when I refresh the page several times when I call this service method:
public Warranty Get(Warranty request)
{
var warranty = new Warranty();
if (request.Id != default(int))
{
warranty = Db.Id<Warranty>(request.Id);
warranty.WarrantyOrder = ResolveService<WarrantyOrderService>().Get(new WarrantyOrder { WarrantyId = warranty.Id });
warranty.WarrantyStatus = ResolveService<WarrantyStatusService>().Get(new WarrantyStatus { Id = warranty.StatusId });
warranty.WarrantyNotes = ResolveService<WarrantyNoteService>().Get(new WarrantyNotes { WarrantyId = warranty.Id });
warranty.WarrantyDialogues = ResolveService<WarrantyDialogueService>().Get(new WarrantyDialogues { WarrantyId = warranty.Id });
warranty.WarrantyCredit = ResolveService<WarrantyCreditService>().Get(new WarrantyCredit { WarrantyId = warranty.Id });
warranty.WarrantyPhotos = ResolveService<WarrantyPhotoService>().Get(new WarrantyPhotos { WarrantyReference = warranty.WarrantyReference });
warranty.WarrantyReport = ResolveService<WarrantyReportService>().Get(new WarrantyReport { WarrantyId = warranty.Id });
}
return warranty;
}
I have changed ConfigureDb
as per @mythz answer below:
private static void ConfigureDb(Container container)
{
var connectionString = ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString;
container.Register<IDbConnectionFactory>(c => new OrmLiteConnectionFactory(connectionString, SqlServerDialect.Provider));
}
The service needs to call out other services to populate the other objects on my Warranty
object, I'm not sure on how to improve this?