超时已过.- 在 ServiceStack 服务中使用 Db [英] Timeout expired. - Using Db in ServiceStack Service
问题描述
我在 ServiceStack 服务中使用 Db
属性来访问我的数据库,但我不时从 IIS 收到以下错误:
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:
超时已过.在从池中获取连接之前超时时间已过.这可能是因为所有池连接都在使用中并且达到了最大池大小.
堆栈跟踪:
[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
我已将 Configure
方法中的 ReuseScope
设置为 ReuseScope.None
我相信这应该在每个请求的基础上关闭连接吗?我在这里做错了什么?
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));
}
配置数据库:
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;
}
我已经按照下面的@mythz 回答更改了 ConfigureDb
:
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));
}
该服务需要调用其他服务来填充我的 Warranty
对象上的其他对象,我不确定如何改进这一点?
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?
推荐答案
IDbConnectionFactory
和所有连接管理器一样是一个线程安全的工厂来创建数据库连接,即它是不是数据库连接本身.它应该被注册为单例.
The IDbConnectionFactory
like all connection managers is a thread-safe factory to create DB Connections, i.e. it's not a DB connection itself. It is supposed to be registered as a singleton.
默认情况下,ServiceStack 的 IOC (Funq) 默认注册为 Singleton,因此正确的注册是:
By default ServiceStack's IOC (Funq) registers as a Singleton by default, so the correct registration is just:
container.Register<IDbConnectionFactory>(c =>
new OrmLiteConnectionFactory(connectionString, SqlServerDialect.Provider));
解析服务
由于 ServiceStack 服务具有利用托管资源的潜力,所以只要它们从另一个服务解析,就应该在 using 语句中使用它们,以便适当地处理它们,例如:
Resolving Services
As ServiceStack Services have the potential to utilize managed resources, they should be used within a using statement whenever they're resolved from another service, so that they're appropriately disposed of, e.g:
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;
}
这篇关于超时已过.- 在 ServiceStack 服务中使用 Db的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!