I’ve written recursive function to retrieve this parent/child style menu from database:
<ul>
<li>
<a href='#'>level1-a</a>
<ul>
<li>
<a href='#'>level2-a1</a>
<ul>
<li><a href='#'>level3-a11</a></li>
</ul>
</li>
<li><a href='#'>level2-a2</a></li>
</ul>
</li>
<li><a href='#'>level1-b</a></li>
<li><a href='#'>level1-c</a></li>
</ul>
I know it’s not a good idea to write such function for retrieving data from database with a recursive function, sometimes it takes long time to run.
It’s my algorithm (C# and VB.net code is provided):
my_function (ID){
WHILE (read_from_table){
PRINT data
my_function(child_id)
}
}
C# code: http://pastebin.com/hsqhYF72
VB.net code: http://pastebin.com/HnyrYnab
Is there any type of variable that is able to store such structure of data to search inside it instead of connecting to a database continually?
Ideally, you want to retrieve all the relevant records at once into an in-memory collection, and then read from that memory collection during your recursion. The paradigm of memoization/caching of records will make this simple, as well as separating your data-access logic from business logic.
First, create a
staticmethod for retrieving data that grabs data from the database the first time, but makes use of its in-memory collection on subsequent calls. I’m assuming that since you are passingfTableName, this method may or may not be used with multiple tables, so the cache is capable of storing multiple tables at once (using aDictionarykeyed on the table name), and treats requests to different tables separately. (WARNING: untested code, but should give you the idea):Since this method is
static, its data is saved during the entire request/response cycle, but not between responses. So this will reduce generating the menu to a single database call, while each time the page is loaded, the data is still loaded new. If your menu data is relatively static, you could go to the next level using the .NET cache with a timeout that will store the database results, for say 30 minutes at a time before refreshing. Then the page could be loaded many times with only a single database call.The code in your
GenerateNestedMenusthat retrieves data from the database would instead make a call toGetMenuLayerwith the appropriate parameters. This method then is responsible for retrieving the data in whatever method it can (the former method doesn’t need to care how it gets there). Behind the scenes, the first time a tablefTableNameis requested, the entire table is downloaded into a local memory cache. Then that memory cache is queried in subsequent calls according to the parameters to return the result rows that can be iterated (this assumes that your dynamic filter logicfClauseis not too complicated, becausedt.Select(only understands a very small subset of basicT-SQLlogic):This is a rough idea of the approach to a solution, which may require some tweaking and experimenting to get everything working.