First we must discuss database format. Only requirement here is need for two fields - ID, ParentID and one Text field. All other fields are optional. For this occasion I have prepared small database with that structure.
Since there can not be more than one DataReader per Connection we can not use recursion right away. Instead, for step one, we will prepare buffer array to hold all required data. This will be few times faster than using one step recursion but it will consume memory like crazy. I think that this solution will do since trees are usually not very big. For this step we user "FillTree" method in DBTree class. This method takes tree object as only parameter and after filling buffer it goes to step two.
Step two is recursion itself. It is contained in "RecurTree" method and takes tree, parentNode and parentID as arguments. Since tree is same as in first step there is not much explanation here. parentNode argument is here for propagation of current node parent throughout recursion. In first step we send value Nothing instead since there is no parent there. If this is case new node will be added to tree itself. ParentID is essentially same thing but used for purpose of filtering out nodes that are irrelevant in current recursion pass. In first pass we send here 0 value since we consider items with parentID=0 to be roots.
And that's all. I think that all of this will be much clearer if you check source.