0

我有一个托管在 IIS 7 上的 WCF Web 服务。该 Web 服务提供 JSON 内容以供在移动应用程序中使用。它使用 MS SQL 2005 之上的实体框架,接口契约如下所示:

   [ServiceContract]
    public interface MyService
    {
        [WebInvoke(Method = "GET", UriTemplate = "/GetStuff?skip={skip}&take={take}&loanAmt={loanAmt}&propertyVal={propertyVal}&Term={Term}&MonthlyRent={MonthlyRent}", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        [OperationContract]
        ProductsDTO GetProducts(int skip, int take, decimal loanAmt, decimal propertyVal, int Term, decimal MonthlyRent);
    }

实现如下所示:

    public ProductsDTO GetProducts(int skip, int take, decimal loanAmt, decimal propertyVal, int Term, decimal MonthlyRent)
    {
       //Some set up code
      using (MyEntities context = new MyEntities()) 
        {
              //Get our products
        }

     return ReturnedList
    }

在第一次运行时,它可能需要长达 15 秒的时间(对于移动应用程序来说是不可接受的),在随后的运行中,数据会在一秒钟内返回。在 5 分钟不活动后,WCF 服务恢复为需要 15 秒才能启动。

我最初认为瓶颈在 IIS7 并且认为我的应用程序池正在关闭。在将应用程序池设置为永不回收并研究 IIS 服务器上的 w3wp.exe 进程后,我意识到情况并非如此。在这五分钟之后关闭的是数据库会话。

在这种情况下,我想保持 SQL 会话打开以立即提供来自 WCF 应用程序的请求,但是,我不想将实体上下文设置为单例或在服务中保持打开状态,因为我知道这是糟糕的做法。我可以将 SQL 连接对象传递给上下文(使用(MyEntities context = new MyEntities(MySQLConnection)))并保持打开状态?或者有人可以提出其他建议吗?

我看过很多帖子,其中的脚本会触及 Web 服务以使其保持活力,这让我感到毛骨悚然,因此我避免走这条路。

你怎么认为?

更新 1

根据 Andomars 的响应,我已将以下初始化代码添加到 WCF 服务。

   public Service1()
        {
            // Blocking call that initializes
            // the service instance
            this.Initialize();
        }

        BackgroundWorker KeepSQLAlive = new BackgroundWorker();

        private void Initialize()
        {
            KeepSQLAlive.DoWork += new DoWorkEventHandler(KeepSQLAlive_DoWork);

            KeepSQLAlive.RunWorkerAsync();
        }

        void KeepSQLAlive_DoWork(object sender, DoWorkEventArgs e)
        {
            Timer pingback = new Timer(180000);

            pingback.Elapsed += new ElapsedEventHandler(pingback_Elapsed);

            pingback.Start();
        }

        void pingback_Elapsed(object sender, ElapsedEventArgs e)
        {
            using (MyEntities context = new MyEntities ())
            {
                context.ExecuteStoreCommand("select @@servername");
            }
        }

这感觉有点像捏造,我有点担心如果不将服务创建为单例,该服务将继续产生 SQL 会话而不会杀死任何会话。但是,如果它有效,这是阻力最小的路径,因为在 Windows 服务中托管此代码将花费更多时间,而且我不清楚如何将其与 IIS 安全性集成(我想使用 SSL)。我将报告上述是否有效。(感谢大家的帮助)

4

2 回答 2

1

select @@servername您可以添加一个每分钟运行(或另一个琐碎查询)的后台线程。这应该使连接池保持温暖。

于 2012-05-22T11:17:44.570 回答
0
  1. Web 服务不应该运行后台线程,所以..
  2. 使用 WCF 合同编写 Windows 服务作为 IIS 和数据库之间的代理。
  3. 确保您在 Windows 服务上使用连接池。
  4. 从您的 Windows 服务中每 30 秒/1 分钟/5 分钟(这一次必须进行测试)从数据库中查询一次。查询后记得关闭您的连接(这不会关闭真正的连接,但会使连接可用于池)。这将使池中至少有一个活动连接为您的请求做好准备。
  5. 在 IIS 上的 WCF 服务和 Windows 服务之间使用管道 (NetNamedPipeBinding)(速度很快)。
  6. 考虑在 IIS 上发布已编译的应用程序。关联
于 2012-05-22T11:33:30.453 回答