C#代码需要更多时间来执行

时间:2016-03-04 07:36:59

标签: c# linq

我是C#的新手,我正在使用Linq对c#中的数据表进行一些操作。我的方法大约需要35秒才能完成处理。有人可以建议如何改善表现吗?

此方法的输入DataTable有35个KPI,每个KPI将为每个会计年度和foreach国家/地区提供13个月的数据。因此,每个会计年度,dt将有35 * 13 = 455条记录。无论如何,将有2个财政年度。所以455 * 2 =每个国家900条记录。因此,我们在输入数据表中记录的记录数小于1000

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();
}

由于

1 个答案:

答案 0 :(得分:1)

该代码示例中存在许多性能问题。一些改进:

  1. dt.AsEnumerable()移到var table = dt.AsEnumerable()这两个循环之外,然后再使用
  2. .ToList()上的KpiValues移至第一个foreach并使用结果列表
  3. 您还要多次查询availablePeriods次(2次.Count(),2次.ToList()),您可以通过拨打.ToList()一次并在所有位置使用该列表来改进
  4. 一般情况下:尝试尽可能少地查询。变量KpiValuesavailablePeriods不是事物列表,而是查询定义。每次从中获取一些数据时,它将执行查询以获取数据,而不是重复使用您可能期望的先前结果。