报告中的自定义聚合函数

时间:2009-10-21 15:35:25

标签: .net linq reporting

我每个类别的每日生产记录,即A类:80吨。每个报告行都如下所示:

             Daily                  Week to Date          Month to Date
             Actual  Plan   Var     Actual  Plan   Var    Actual   Plan   Var
Category A   100     110    -10     230      300   -70    900      1200  -300
Category B   etc. etc.

A类:在本周的第2天,开采了10次矿石。在每日实际值下,10吨/跳,相当于您在上面看到的100吨。因此,对于A类,我需要一个定义为“输入* 10”的公式,但它并不总是一个简单的乘法因子。我需要存储输入的任何公式 - >每日数字。在第1天,我有一个132吨的实际值,但是已知2吨/天的正误差,所以周至实际不仅仅是一个简单的总和,需要调低。所以我需要一个特殊的每周实际公式,如(d1 + ... + dn) - 2n。

B类:在第2天,测定结果得出每吨矿石x千克镍。对于B类,我需要每天的实际镍/矿石配方* 100,但我必须能够为B类的每日实际值分配任何公式。对于周至今的实际情况,我是使用均值,中位数还是模式,是否有调整?

在我的类别数据库表中,我有例如。

A类:UnitOfMeasure = Tons,DailyFormula =“input * 10”,WeeklyFormula =“(d1 + ... + dn) - 2n”

在计算报表中A类行的值时,我的代码需要应用类别A的唯一公式。我想尝试将其用于针对原始数据的LINQ查询。

编辑:我需要一种方法让用户定义这些公式,并根据存储在数据库列中的公式在运行时动态解析和评估它们。

1 个答案:

答案 0 :(得分:1)

我希望我理解正确。我有自定义分组的想法,用于从类别到分组方法的映射。

我已经简化了一点,以便明确答案:

假设报告输入的行属于此类:

public class Production
{
    public string Category { get; private set; }
    public int DayIndex { get; private set; }
    public double Input { get; private set; }
}

在这个类中,我们有类别,当天的指数和可以代表矿石开采量的输入。

Production[] results = // The inputs to the report

// The map from category to the grouping method
var groupingMethods =
    new Dictionary<string, Func<IGrouping<string, Production>, double>>
      {
          {
              "ore", // Category name
              grouping =>                                        // The method
              grouping.Sum(production => production.Input) * 10  // grouping ore 
          },                                                     // rows
          {
              "nickel",
              grouping =>
              grouping.Sum(production => production.Input) - 2 * grouping.Count()
          }
      };

// The query create groups based on the category
var report = from result in results
             group result by result.Category
             into categoryResults
             select new
                  {
                     // Created anonymous object with Category
                     Category = categoryResults.Key,
                     // Find the grouping method of the category, invokes it
                     // and store the result in Week column
                     Week = groupingMethods[categoryResults.Key](categoryResults)
                  };

这里的主要思想是“切换”方法取决于类别。它可以很容易地按其他标准更改为分组,当然也可以添加和更改分组。此外,对于其他列,可以通过为新列添加另一个字典来轻松调整。

例如:

var weekMethods =
    new Dictionary<string, Func<IGrouping<string, Production>, double>>() ...

var monthMethods =
    new Dictionary<string, Func<IGrouping<string, Production>, int>>() ...


from result in results
group result by result.Category
into categoryResults
select new
       {
           Category = categoryResults.Key,
           Week = weekMethods[categoryResults.Key](categoryResults),
           Month = monthMethods[categoryResults.Key](categoryResults)
       };