需要在

时间:2015-06-17 11:08:46

标签: c# asp.net sql-server excel datatable

我已经写了一个asp.net网站,用于创建充满指定项目的报告(到Excel中)。我通过EF从SQL DB获取这些项目。查询效果很好,需要大约2000个项目大约1ms。

var itemsToQuery = (from i in context.item
    where ......
    .....
    .....
    orderby .......
    select new
    {
    fields.....
});

现在对我来说很棘手。 Foreach项目我必须从数据库中查询额外数据(没有机会通过第一个查询获取这些数据)。我只使用一个数据库连接来保证安全时间(对于主查询和方法中的所有其他查询)。我认为我的性能问题从这里开始。我有2000个项目,以下循环如下所示:

foreach(var item in itemsToQuery)
{
      another query;
      another query;
      another query;
      etc.....
      // at the end it looks like
      datatable.add(item.name, item.number, item.stuff ......);
}

所以我为这2000个项目中的每一个做了另外8个查询。这个foreach大约需要5分钟(取决于项目数)。之后我需要这个DataTable来填充我的Excel表格。这样做很好,并且快速"。

你能否给我一些专家建议如何使这个循环,查询或填充DataTable更高效?

我考虑过使用多任务处理并创建一个站点,您可以在其中查看Excel的状态(通过ajax调用),一旦完成,您就可以下载它。现在我只是阻止这个网站的用户界面,用户必须坐在屏幕前,直到完成没有任何信息,他需要等待多长时间。带有gif和js的屏幕示例,用于运行时钟:

graphic while blocking ui

一件重要的事情 - 我不能在数据库中创建视图或存储过程,因为我不允许这样做。我必须在后面的代码中执行每个查询等。

我知道该程序是业余的,但这就是我必须紧急改变的原因。

[编辑]

以下是我所讨论的示例查询!仅供参考 - 我没有写过每个查询。其中一些(如ownermonthlyWorkTime)来自外部资源。

String changeDate = CalcÄnderungsDat(context
                     .ticket_history
                     .FirstOrDefault(x => x.history_type_id == 25 && x.ticket_id == item.ticketID).change_time.ToString());




String finishdate = CalcFinishDat((from tih in context.ticket_history
                      where (tih.name == "Reset of unlock time." && tih.ticket_id == item.ticketID)
                      || (tih.state_id == 2 && tih.history_type_id == 1 && tih.ticket_id == item.ticketID)
                      select tih.change_time).Max().ToString());


try
{
  string owner= (from a in context.article
                 where
                 item.ticketID == a.ticket_id &&
                 a.id ==
                 (from art in context.article
                 where art.a_subject.Contains("esitzer")
                 && art.ticket.id == item.ticketID
                 && art.ticket_id == art.ticket.id
                 select new { art.id }).Max(p => p.id)
                 select new { a.a_from }).FirstOrDefault().a_from;
}
catch (Exception)
{
 string owner = (from a in context.article
                 where a.ticket.id == item.ticketID && a.ticket_id == a.ticket.id &&
                 a.id ==
                 (from art in context.article
                 where art.ticket.id == item.ticketID
                 && art.ticket_id == art.ticket.id
                 select new { art.id }).Min(p => p.id)
                 select new { a.a_from }).FirstOrDefault().a_from;
}

decimal? monatszeit = (from ta in context.time_accounting
                      where
                      ta.change_time >= startdat &&
                      ta.change_time <= enddat &&
                      ta.ticket_id == item.ticketID
                      group new { ta } by new
                      {
                         ta.ticket_id,
                         ta.ticket.id,
                         ta.ticket.tn
                      } into g
                      select new
                      {
                           Zeiteinheit = (Decimal?)g.Sum(p => p.ta.time_unit),
                      }).SingleOrDefault().Zeiteinheit;

等等。总体而言,有7个查询和1个外部方法用于计算主查询中每个项目的特殊日期(此方法不应该是问题)。我如何将它们放在一个完整的查询中?它会提高我的表现吗?

[编辑 - 另一个尝试!]

您对此流程图有什么看法? enter image description here

  • 客户端发送请求到服务器服务器写入一个条目 &#34;工作&#34;数据库中的表
  • 发送请求后,客户端从DB获取job_ID 立即
  • 使用此ID客户端可以为进度(状态)执行AJAX调用
  • 如果有新工作,web服务会每秒检查一次 DB中的状态-1
  • 为状态为-1的每个作业创建一个新任务
  • 在此任务中将使用ReportMaker.GenerateReport(idAUFTRAG)方法 称为
  • ReportMaker有一个Event ReportProgress
  • 调用者(Task)订阅此事件并将每个更改写入 数据库
  • 数据库访问器 - &gt;任务
  • 客户端执行Ajax回调

那肯定会提升性能!对于这么小的项目来说,这听起来有多大工作吗?

1 个答案:

答案 0 :(得分:0)

您可以考虑为已检索的数据创建缓存解决方案。因此查询结果将存储在内存中,并且每次都不会检索它,因此性能会大大提高。

您必须考虑刷新缓存的频率。其他选项是检查是否出现了一些新数据,并进行仅检索最新数据的查询。