从数据网格视图行生成统计信息



我正在处理一个项目的一部分,该部分解析来自Postgres数据库服务器的日志。该应用程序是在C sharp Framework 4.0中开发的。

生成日志并将其显示在 DataGridView 上,其中包含以下列

resultCode       Statement                  Starttime                   Duration
XT001         select * from PizzaMade    01-02-2012 03:10:14         00:04:10
  • 有许多相同格式的日志行。
  • 通过解析文本文件从另一个循环填充数据网格视图。

我的工作是从网格中可用的数据中生成以下格式的统计信息

Statement                                 Count        countpercent                    Occurs_on
select * from PizzaMade                     3             1.42        01/02 at 03pm   [00:04:10], 01/02 at 04 [00:01:04]
select id,qty,table from PizzaMade          12             5.12           ...........

所以基本上统计数据反映了以下内容

  • a( 执行的语句
  • b( 计算它在网格中出现的次数
  • c( 计数百分比,这基本上是此语句占总数的部分
  • d( 包含开始时间、持续时间的串联字符串

» 统计数据首先生成为数据表,使用 for 循环

foreach(DataGridViewRow dr in LogGrid.Rows)
{
// search in the Datatable if the statement is present
// if it is then add count , add starttime and duration to the column
// if not then add a newrow
}

» 填充数据表后,我使用循环来计算总计数

int totalcount = 0;
foreach (DataRow drin StatTable.Rows)
{
totalcount = totalcount + Convert.ToInt32(dr["count"].ToString());
}

» 计算计数后,有一个循环来计算百分比

foreach (DataRow dr in StatTable.Rows)
{
    int c = Convert.ToInt32(dr["count"].ToString());
    dr["countpercent"] = (c/totalcount)*100;
}

尽管一切看起来都很好,但整个方法由于行数众多而缓慢。

  • 您能否提出提高性能的方法。

谢谢阿文德

由于您正在解析文本日志,因此它可能会通过不在网格中而是在对象中操作来提高性能。此外,网格可以绑定到已分析日志列表。可能是这样的:

public class LogItem
{
    public string ResultCode { get;set;}
    public string Statement { get;set;}
    public DateTime StartTime { get;set;}
    public TimeSpan Duration { get;set;}
}

然后,您的网格可以绑定到包含所有已解析日志项的 BindingList。拥有列表后,您可以以更统一的方式访问数据:

foreach (string statement in logItems.Select(x => x.Statement).Distinct())
{
    int count = logItems.Count(x => x.Statement == statement);
    double percentage = count / logItems.Count(); 
    // any additional data
}

如果您想提高性能和花哨性,可以将所有解析的日志文件保存到数据库,并为必要的数据创建查询。

我有一些建议,

您可以使用 LINQ 对循环过程使用类似的东西。基本上,LINQ 使用经过优化的查询,这提供了出色的性能。

 DataTable obj = new DataTable();
        obj.Columns.Add("count",typeof(Int32));
        DataRow dr = obj.NewRow();
        dr[0] = "10";
        obj.Rows.Add(dr);
        DataRow dr1 = obj.NewRow();
        dr1[0] = "5";
        obj.Rows.Add(dr1);
        obj.Columns.Add("countpercentage");
        int intCount = (from DataRow drrow in obj.Rows
                        select drrow.Field<int>("count")).Sum();
        (from DataRow drtemp in obj.Rows
         select drtemp).ToList<DataRow>()
         .ForEach(x => x.SetField<string>("countpercentage", ((x.Field<Int32>("count")*100) / intCount).ToString()));

最新更新