I have a simple CMS system, that has a simple tree hierarchy:
We have pages A through E that has the following hierarchy:
A -> B -> C -> D -> E
All the pages are the same class, and have a parent-child relationship.
Now, let’s say I have a property I want inherited among the pages. Let’s say A is red:
A (red) -> B -> C -> D -> E
In this case, B through E would inherit “red”.
Or a more complex scenarios:
A (red) -> B -> C (blue) -> D -> E
B would inherit red, and D/E would both be blue.
What would be the best way to solve something like this? I have a tree structure with over 6,000 leafs and about 100 of those leaves have inheritable properties. Those 100 or so leaves have their properties saved in the database. For leaves without explicit properties, I look up the ancestors and use memcached to save the properties. Then there are very overly-complex algorithms to handle expiring those caches. It’s terribly convoluted and I’d like refactor to a more cleaner solution / data structure.
Does anybody have any ideas?
Thanks!
If your problem is performance-related…
I assume you’d want to save on memory of all these inheritable properties (or perhaps you have a lot of them), otherwise this can be trivially solved with virtual properties.
If you need sparse inheritable properties, say if you are modelling how HTML DOM properties or CSS properties propagate, you’ll need to:
Of course you can add more functionalities on top of this. This is similar to how Windows Presentation Foundation solves this problem via DependencyProperty.
If your problem is database-related…
If instead your problem is to avoid reading the database to walk up the tree (i.e. loading the parents to find inherited properties), you’ll need to do some sort of caching for the parent values. Or alternatively, when you load a leaf from the database, you can load all its parents and create a master merged properties dictionary in memory.
If you want to avoid multiple database lookups to find each parent, one trick is to encode the path to each node into a text field, e.g. “1.2.1.3.4” for a leaf on the 6th level. Then, only load up nodes that have paths which are beginning substrings. You can then get the entire parents path in one SQL query.