Timed out. - Using Db in ServiceStack Service

I use the Db property in ServiceStack to access my database, but from time to time 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 installed ReuseScope in the Configure method on ReuseScope.None , which should close the connection for each request, I suppose? 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 detailed diagnostics, 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 modified ConfigureDb according to @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 must call other services to populate other objects on my Warranty object, I'm not sure how to improve this?

+6
source share
1 answer

IDbConnectionFactory , like all connection managers, is a thread-safe factory for creating database connections, i.e. This is not a database connection. It must be registered as a single.

By default, ServiceStack IOC (Funq) is used as Singleton by default, so the correct registration is:

 container.Register<IDbConnectionFactory>(c => new OrmLiteConnectionFactory(connectionString, SqlServerDialect.Provider)); 

Permissive Services

Because ServiceStack services can use managed resources, they should be used in the using statement whenever they are resolved from another service, so they are removed accordingly, for example:

 using (var orders = ResolveService<WarrantyOrderService>()) using (var status = ResolveService<WarrantyStatusService>()) { var warranty = new Warranty { WarrantyOrder = orders.Get(new WarrantyOrder { WarrantyId = warranty.Id }), WarrantyStatus = status.Get(new WarrantyStatus { WarrantyId = warranty.StatusId }), //etc } return warranty; } 
+5
source

Source: https://habr.com/ru/post/957909/


All Articles