0

現在、Web サービスからレポートを生成するアプリケーションを使用しています。レポートは基本的に、(ストアド プロシージャを使用して) WebService によってデータベースから取得されるデータのテーブルです。

最初の 50 件のレコードが画面に表示されますが (ビューに送信されます)、ユーザーがクリックしてクエリ全体を Excel スプレッドシートにダウンロードできるボタンもあります。これは、クエリの結果をモデルに渡し、スプレッドシートの作成に使用される stringbuilder に書き込むことによって実現されます。このアクション メソッドのコードは次のとおりです。

// WebService call
var reportResult = SubscriberService.GetReport(reportName, criteria.CurrentPageNumber - 1, 0, getReportParameters(model.GroupId, criteria));
  model.Result = getModel(reportResult);     

  // if file name is not ended with .csv we there it as prefix and file will be prefix_{date}.csv
  if (String.IsNullOrEmpty(fileName) || fileName.LastIndexOf(".csc", StringComparison.InvariantCultureIgnoreCase) != fileName.Length - 4)
    fileName = string.Format("{0}_{1}.csv", fileName, DateTime.Now.ToShortDateString());

  HttpContext.Response.ContentType = "text/csv";
  HttpContext.Response.AddHeader("Content-Disposition", "attachment; filename=" + fileName);

  if (model.Result != null)
  {
    StringBuilder sb = new StringBuilder();
    exportRowHeader(sb);
    HttpContext.Response.Write(sb.ToString());
    sb.Clear();

    foreach (var item in model.Result.Members)
    {
      exportRowData(sb, model.Result, item);
      HttpContext.Response.Write(sb.ToString());
      sb.Clear();
    }
    HttpContext.Response.Write(sb.ToString());
  }
  else
  {
    HttpContext.Response.Write(ReportResources.Report_Exporting_NoDataAvailable);
  }

  HttpContext.Response.Flush();

ここでの問題は、大規模なクエリの場合、Web サービスとの通信に時間がかかりすぎてタイムアウトになることです。WebService 経由で送信できるデータの最大量にも問題があります。

そこで私が考えていたのは、WebService 呼び出しを分割することです。WebService には、送り返す結果をページ分割する機能があります。したがって、基本的に一度に 200 件の結果を呼び出します (すべての結果が返されるまで)。

追加の stringbuilder オブジェクトを作成し、それらをすべて組み合わせて結果の 1 つのスプレッドシートを作成するだけで、これを行うことは可能ですか? これはメモリの問題につながりますか?

これが不可能と思われる場合は、別の解決策を提案できますか?

4

1 に答える 1

0

do-while ループを使用することで、最終的にかなり楽に動作するようになりました。72,000 行 25 列のスプレッドシートを作成するのに 3 分半かかりましたが、これらすべてを HttpContext.Response に保持してもメモリの問題はないようです。

int pageNum = 0;
  int pageSize = 2000;




  // if file name is not ended with .csv we there it as prefix and file will be prefix_{date}.csv
  if (String.IsNullOrEmpty(fileName) || fileName.LastIndexOf(".csc", StringComparison.InvariantCultureIgnoreCase) != fileName.Length - 4)
    fileName = string.Format("{0}_{1}.csv", fileName, DateTime.Now.ToShortDateString());

  HttpContext.Response.ContentType = "text/csv";
  HttpContext.Response.AddHeader("Content-Disposition", "attachment; filename=" + fileName);

  do
  {

    var reportResult = SubscriberService.GetReport(reportName, pageNum, pageSize,
                                                   getReportParameters(model.GroupId, criteria));
    model.Result = getModel(reportResult);

    if (model.Result != null)
    {
      StringBuilder sb = new StringBuilder();

      if (pageNum == 0)
      {
        exportRowHeader(sb);
        HttpContext.Response.Write(sb.ToString());
        sb.Clear();
      }

      foreach (var item in model.Result.Members)
      {
        exportRowData(sb, model.Result, item);
        HttpContext.Response.Write(sb.ToString());
        sb.Clear();
      }
      HttpContext.Response.Write(sb.ToString());
    }
    else
    {
      HttpContext.Response.Write(ReportResources.Report_Exporting_NoDataAvailable);
      break;
    }

    pageNum++;

  } while (model.Result.Members.Count==pageSize); 

  HttpContext.Response.Flush();
于 2012-11-29T12:52:48.423 に答える