2016-03-04 26 views
0

我是C#的新手,我正在使用Linq在c#中的数据表中执行一些操作。我的方法需要大约35秒才能完成处理。有人可以建议如何提高性能?C#代码需要更多时间来执行

该方法的输入数据表有35个关键绩效指标,每个会计年度和每个国家的每个关键绩效指标都有13个月的数据。因此,dt每个财政年度将有35 * 13 = 455条记录。无论如何,会有2个会计年度。所以每个国家455 * 2 = 900条记录。因此,我们正在采取有关的记录数在输入数据表

void NeedtoImprovePerformance(DataTable dt) 
{ 
    DataView dv = dt.DefaultView; 
    dv.Sort = "Fiscal_Year ASC"; 
    dt = dv.ToTable(); 

    var kpilist = from table in dt.AsEnumerable() 
        orderby table.Field<int>("Sub_Service_Type_Id") 
        group table by new { kpiName = table["KpiName"] } into groupby 
        select new 
        { 
         value = groupby.Key, 
         columnvalues = groupby 
        }; 

    var uniqueCountry = from table in dt.AsEnumerable() 
         group table by new { country = table["CountryName"] } into groupby 
         select new 
         { 
          value = groupby.Key, 
          columnValues = groupby 
         }; 

    foreach (var kpi in kpilist) 
    { 
     var KpiValues = from table in dt.AsEnumerable() 
         where table.Field<string>("KpiName") == kpi.value.kpiName.ToString() 
         select table; 

     foreach (var countryName in uniqueCountry) 
     { 
      var availablePeriods = from table in dt.AsEnumerable() 
            where table.Field<string>("KpiName").ToString() == kpi.value.kpiName.ToString() && 
            table.Field<string>("CountryName").ToString() == countryName.value.country.ToString() 
            select table.Field<int>("Period").ToString(); 

      if (availablePeriods.Count() < 13 && availablePeriods.Count() > 0) 
      { 
       for (int period = 5; period < 17; period++) 
       { 
        DataRow dr = dt.NewRow(); 
        if (!availablePeriods.ToList().Contains(period.ToString())) 
        { 
         dr[1] = KpiValues.ToList()[0]["KpiName"].ToString(); 
         dr[2] = countryName.value.country.ToString(); 
         dr[3] = (period).ToString(); 

         var availableFiscalYear = from table in dt.AsEnumerable() 
                where table.Field<int>("Period").ToString() == period.ToString() 
                select table.Field<string>("Fiscal_Year").ToString(); 
         if (availableFiscalYear == null || availableFiscalYear.Count() == 0) 
         { 
          if (ddlFiscalYear.SelectedItem.Text == ddlFiscalYear.Items[ddlFiscalYear.Items.Count - 1].Text) 
          { 
           if (period > 10) 
            dr[4] = ddlFiscalYear.SelectedValue.ToString(); 
           else 
            dr[4] = (Convert.ToInt32(ddlFiscalYear.SelectedValue) - 1).ToString(); 

           if (period == Convert.ToInt32(ddlMonth.SelectedValue) || period < Convert.ToInt32(ddlMonth.SelectedValue)) 
            dr[4] = (Convert.ToInt32(ddlFiscalYear.SelectedValue) + 1).ToString(); 
          } 
          else 
          { 
           if (period > Convert.ToInt32(ddlMonth.SelectedValue)) 
            dr[4] = (Convert.ToInt32(ddlFiscalYear.SelectedValue) - 1).ToString(); 
           else 
           { 
            if (period == Convert.ToInt32(ddlMonth.SelectedValue)) 
             dr[4] = (Convert.ToInt32(ddlFiscalYear.SelectedValue) + 1).ToString(); 
            else 
             dr[4] = ddlFiscalYear.SelectedValue.ToString(); 
           } 
          } 
         } 
         else 
         { 
          dr[4] = availableFiscalYear.ToList()[0].ToString(); 
         } 

         dr[5] = ""; 
         dr[6] = KpiValues.ToList()[0]["Frequency"].ToString(); 
         dr[7] = KpiValues.ToList()[0]["Sub_Service_Type_Id"].ToString(); 
         dr[8] = KpiValues.ToList()[0]["Service_Type_Id"].ToString(); 
         dr[9] = KpiValues.ToList()[0]["ServiceName"].ToString(); 
         dr[10] = KpiValues.ToList()[0]["OrderBy"]; 
         dt.Rows.Add(dr); 
        } 

        if (ddlMonth.SelectedValue == period.ToString()) 
        { 
         var selectedPeriod = availablePeriods.Where(k => k == ddlMonth.SelectedValue).ToList(); 
         if (selectedPeriod != null && selectedPeriod.Count == 1) 
         { 
          var PeriodFiscalYear = from table in dt.AsEnumerable() 
                where table.Field<string>("KpiName").ToString() == kpi.value.kpiName.ToString() && 
                table.Field<string>("CountryName").ToString() == countryName.value.country.ToString() 
                && table.Field<int>("Period") == period 
                select table.Field<string>("Fiscal_Year"); 
          dr = null; 
          dr = dt.NewRow(); 
          dr[1] = KpiValues.ToList()[0]["KpiName"].ToString(); 
          dr[2] = countryName.value.country.ToString(); 
          dr[3] = (period).ToString(); 

          var availableFiscalYear = from table in dt.AsEnumerable() 
                 where table.Field<int>("Period").ToString() == period.ToString() && 
                 table.Field<string>("Fiscal_Year").ToString() != PeriodFiscalYear.ToList()[0] 
                 select table.Field<string>("Fiscal_Year").ToString(); 
          if (availableFiscalYear == null || availableFiscalYear.Count() == 0) 
          { 
           if (ddlFiscalYear.SelectedItem.Text == ddlFiscalYear.Items[ddlFiscalYear.Items.Count - 1].Text) 
           { 
            if (period > 10) 
             dr[4] = ddlFiscalYear.SelectedValue.ToString(); 
            else 
             dr[4] = (Convert.ToInt32(ddlFiscalYear.SelectedValue) - 1).ToString(); 

            if (period == Convert.ToInt32(ddlMonth.SelectedValue) || period < Convert.ToInt32(ddlMonth.SelectedValue)) 
             dr[4] = (Convert.ToInt32(ddlFiscalYear.SelectedValue) + 1).ToString(); 
           } 
           else 
           { 
            if (period > Convert.ToInt32(ddlMonth.SelectedValue)) 
             dr[4] = (Convert.ToInt32(ddlFiscalYear.SelectedValue) - 1).ToString(); 
            else 
            { 
             if (period == Convert.ToInt32(ddlMonth.SelectedValue)) 
              dr[4] = (Convert.ToInt32(ddlFiscalYear.SelectedValue) + 1).ToString(); 
             else 
              dr[4] = ddlFiscalYear.SelectedValue.ToString(); 
            } 
           } 
          } 
          else 
          { 
           dr[4] = availableFiscalYear.ToList()[0].ToString(); 
          } 

          dr[5] = ""; 
          dr[6] = KpiValues.ToList()[0]["Frequency"].ToString(); 
          dr[7] = KpiValues.ToList()[0]["Sub_Service_Type_Id"].ToString(); 
          dr[8] = KpiValues.ToList()[0]["Service_Type_Id"].ToString(); 
          dr[9] = KpiValues.ToList()[0]["ServiceName"].ToString(); 
          dr[10] = KpiValues.ToList()[0]["OrderBy"]; 
          dt.Rows.Add(dr); 
         } 
        } 
       } 
      } 
     } 
    } 

    dv = dt.DefaultView; 
    dv.Sort = "KpiName ASC, Fiscal_Year ASC, Sub_Service_Type_Id ASC"; 
    dt = dv.ToTable(); 
} 

感谢

+0

在这样的情况下,只有一件事情要做,那就是使用一个分析器来准确找出吃东西的时间。 –

+0

当你没有说出瓶颈在哪里或者它应该做什么的时候,它有点难...虽然3个嵌套for循环可能不是最好的东西(很难说)(不要介意linq查询) – Sayse

+0

foreach var countryName in uniqueCountry)对kpilist中的每个kpi花费近1秒。 kpilist拥有大约35个KPI,因此需要大约35秒。 – Kalyan

回答

1

有一些代码示例在很多性能问题是小于1000。一些改进:

  1. 移动dt.AsEnumerable()var table = dt.AsEnumerable()两个环路之外,使用替代
  2. KpiValues移动.ToList()到第一的foreach和使用结果列表
  3. 你也是availablePeriods多次查询(2X .Count(),2x .ToList()),您可以通过调用.ToList()一次并在所有位置上使用该列表来改善此问题。

一般来说:尽可能少地查询。变量KpiValuesavailablePeriods不是事物列表,而是查询定义。每次你得到一些数据,它会执行查询来获取数据,而不是重复使用以前的结果。

相关问题