2009-10-21 6 views
-1

J'ai des enregistrements journaliers de production par catégorie, c'est-à-dire la catégorie A: 80 tonnes. Chaque ligne de rapport ressemblera à ceci:Fonctions d'agrégation personnalisées dans les rapports

   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. 

Catégorie A: Le jour 2 de la semaine, 10 bennes de minerai sont extraites. À 10 tonnes/skip, cela équivaut aux 100 tonnes que vous voyez ci-dessus, sous Daily Actual. Donc, pour la catégorie A, j'ai besoin d'une formule définie qui dit "entrée * 10", mais ce ne sera pas toujours un simple facteur de multiplication. J'ai besoin de stocker n'importe quelle formule pour l'entrée -> chiffre quotidien. Le jour 1, j'ai un réel de 132 tonnes, mais une erreur positive de 2 tonnes/jour est connue, donc la semaine à date réelle n'est pas seulement une somme simple et doit être ajustée à la baisse. J'ai donc besoin d'une formule spéciale pour les résultats de la semaine à date, comme (d1 + ... + dn) - 2n. Catégorie B: Le jour 2, un résultat d'analyse donne x kilogrammes de nickel par tonne de minerai. Pour la catégorie B, j'ai besoin d'une formule réelle quotidienne de nickel/minerai * 100, mais encore une fois, je dois être en mesure d'assigner une formule aux données réelles quotidiennes pour la catégorie B. Pour les résultats réels hebdomadaires, dois-je utiliser moyenne, médiane ou mode, et y a-t-il un ajustement?

Dans ma table Catégories DB, j'ai par exemple.

Catégorie A: UnitOfMeasure = tonnes, DailyFormula = "entrée * 10", WeeklyFormula = "(d1 + ... + dn) - 2n"

Mon code doit appliquer les formules uniques pour la catégorie A lors du calcul valeurs d'une ligne de catégorie A dans le rapport. Je veux essayer de travailler ceci dans une requête LINQ par rapport aux données brutes.

EDIT: J'ai besoin d'un moyen de laisser l'utilisateur définir ces formules et de les analyser et les évaluer dynamiquement au moment de l'exécution, en fonction de la formule stockée dans une colonne DB.

Répondre

1

J'espère avoir bien compris. L'idée que j'ai pour le groupement personnalisé est utilisée par carte de la catégorie à la méthode de regroupement.

Je l'ai simplifié un peu pour rendre la réponse claire:

Disons que les lignes de la saisie du rapport sont de cette classe:

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

Dans cette classe, nous avons la catégorie, l'indice de le jour et l'apport qui peut représenter par exemple la quantité de minerai extrait.

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

L'idée principale ici est que les méthodes de "commutation" dépendent de la catégorie. Il peut être facilement changé en groupe par d'autres critères et bien sûr ajouter et modifier les groupements. En outre, pour les colonnes supplémentaires, il peut facilement être ajusté en ajoutant un autre dictionnaire pour la nouvelle colonne.

Par exemple:

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) 
     }; 
+0

Vous parfaitement compris, mais malheureusement j'avais omis un facteur important, et qui est que l'utilisateur doit être en mesure de définir la fonction et le code de rapport lu à partir de la base de données. Je suppose qu'avec votre aide, et un analyseur d'expression modeste d'ailleurs, et les arbres d'expression, je peux le faire. – ProfK

Questions connexes