Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C# Trees
I'm working on a Product BOM (bill of material) and I'm stucked. This is my class diagram:
•A Component has ComponentItems. A ComponentItem has a Component and a quantity. Example: Component ABC has 3 Component C1 and 2 Component C2.
•A Product has ComponentItems and ProductItems (similar to ComponentItems but for Products).

Each Component has a unit cost so a ComponentItem has a total cost. And a Component composed by ComponentItems has a total cost too (sum of ComponentItems cost).
 
This structure lets me create any Product/Component hierarchy. I'm validating loops in insert/update of products and components.
 
I want to have each cost updated in database, I don't want to calculate cost using objects every time I have to use a Product/Component. I mean, if I update the unit cost of Component ABC, his parent component cost should be updated and so on --> the update is propagated in the hierarchy.
 
What's the best way to implement this? I was thinking of a tree representation. When a component is updated, I retrieve all related components/products and build a tree. Then I have to update first level parents of the component and do the same with parents of this parents.
 
This wasn't easy to explain, I hope it's clear enough.
 
Thanks in advance.
Posted 26-Jul-11 2:48am

1 solution

Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

First question: how complex are your components? Recalculating the price each time may not be a problem, and means that you have no issues with caching and making sure updates work.
 
What you essentially want for rebuilding the prices is a reverse tree: starting from the component that you changed the price on, look up all its ancestors and update their prices. Pseudocode:
void UpdatePrice(Component target, decimal newPrice){
 target.Price = newPrice;
 List<Component> parents = select from components where componentWithUpdatedPrice in Children;
 foreach(Component p in parents){
  UpdatePrice(p, p.RecalculatePrice());
 }
}
 
You can probably write that query as a bona fide LINQ query but I forget the syntax. I don't see any way to avoid recursion as it's tree walking. If your system permits circular references then you also need to leave yourself a 'passing note' so you don't get into an infinite loop.
  Permalink  
Comments
fgoldenstein at 26-Jul-11 9:44am
   
Thanks for your answer!

Recalculating cost and price:
I thinks recalculating the cost is an issue because of performance problems. Imagine a producto composed by many products and components. Each children (product or component) composed by many products and components and so on. When you have to calculate cost of a product, it can get really messy. And price, sometimes, depends on cost (price can be fixed or variable).
Also, I prefer to have my DB with summarized values so I can create queries faster.

UpdatePrice method:
Your implementation is OK but I'm afraid of a situation. Take a look at this example:

A------- B
| | | | |
D E E F G

A = 2B + 5D + 2E
B = E + 5F + 8G

When E changes its cost, you have to get its parents, A and B in this case. A gets updated and the B is updated to. A has no parents but B has A as its parent. So you have to update A again.
Maybe this sample is short but this can get very huge.

Thanks again for your help.
fgoldenstein at 26-Jul-11 9:46am
   
I deleted the "solution" I wrote because it was a comment, as BobJanova said. This is his comment, which was deleted after I deleted the solution:
 
"First thing, you should respond to a solution by using 'Add Comment', not posting a new solution.
 
If it is not possible for references to be circular, you can solve this by pre-walking and whenever you trip over one of these, switch the order of the parents." BobJanova

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 Kornfeld Eliyahu Peter 169
1 George Jonsson 145
2 Zoltán Zörgő 139
3 PIEBALDconsult 130
4 OriginalGriff 120
0 OriginalGriff 6,165
1 DamithSL 4,658
2 Maciej Los 4,107
3 Kornfeld Eliyahu Peter 3,649
4 Sergey Alexandrovich Kryukov 3,382


Advertise | Privacy | Mobile
Web04 | 2.8.141220.1 | Last Updated 26 Jul 2011
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100