2016-03-04 81 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不是事物列表,而是查詢定義。每次你得到一些數據,它會執行查詢來獲取數據,而不是重複使用以前的結果。

相關問題