超时已过.- 在 ServiceStack 服务中使用 Db [英] Timeout expired. - Using Db in ServiceStack Service

查看:44
本文介绍了超时已过.- 在 ServiceStack 服务中使用 Db的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆