views:

611

answers:

4

I use the code below as an HTMLHelper which gets data from the database and loops over it to display a menu. This is fairly straightforward as you can see however, what if you have a database table using the adjacent model of heirarchies eg/ID, ParentID, OrderID. Easy to see whats going on but recursion is needed to get this data out properly. Is writing a C# recursive function acceptable? If so can someone help me with that? The expected output is something similar to this..

<ul>
  <li>Item1
    <ul>
      <li>SubItem1</li>
    </ul>
  </li>
</ul>

SQL 2008 has a Heirarchy datatype now so I am not sure if this will help things?

I would also like some way of enabling users to decide what goes in a menu for example, a list of items that can go in the menu and then choosing these items and their positions in the heirarchy. Once a saved button is pressed it will store this heirarchy in the database.

Am I asking too much, I'm sure this must be quite a common scenario?

Here is my HTMLHelper code if anyone wants to use it...

 public static string Menu(this HtmlHelper helper, int MenuCat)
{

    string menuHTML = "<ul id=\"menu\">";

    var route = helper.ViewContext.RequestContext.RouteData;
    string currentPageName = route.GetRequiredString("id");

    DB db = DB.CreateDB();

    //var result = from p in db.WebPages where p.CategoryID == 9 select p;
    var result = from p in db.WebPages select p;

    foreach (var item in result)
    {
        if (item.Name == currentPageName)
        {

            menuHTML += "\n\t<li>" + helper.ActionLink(item.Name, "Details", "Dinner", new { id = item.ID }, new { @class = "selected" }) + "</li>";
        }
        else
        {
            menuHTML += "\n\t<li>" + helper.ActionLink(item.Name, "Details", "Dinner", new { id = item.ID }, null) + "</li>";
        }
    }

    menuHTML += "\n</ul>\n";

    return menuHTML;


}
+1  A: 

I would do two things here: don't bother rendering this yourself: use jQuery. If you Google "jquery menu" you'll find hundreds of links.

Next, put the ordering logic on your app, you don't need the DB to do this as it soaks up cycles and (from what I've read) isn't terribly efficient. This is simple looping logic with a self-referencing join that Linq is perfect for.

Hand this off to jQuery, adn you're good to go without hard-coding HTML in code :)

Rob Conery
Is jQuery the way to go? I would of thought the least javascript the better?
Jon
The jQuery menus expect the HTML as <ul><li>....and then they apply their magic so I might as well do it as a CSS Menu?
Jon
A: 

If you are using Sql server 2005 take a look to Common Table Expression (CTE) (google with CTE hierarchical data). It allows you to create a view displaying the complete hierarchy.

But, how much depth level are you displaying in the menu? Usually you only need to show directy childs and go down in the hierarchy as the user clicks the links. (No recursion needed)

Drevak
A: 

See here for the answer

Jon
A: 

I always use recursive table-valued functions for fetching hierarchical data in SQL server.

See an example here: blogs.conchango.com/christianwade/archive/2004/11/09/234.aspx

Unfortunately, there is a recursion limit (32 levels maximum) for SQL Server User Defined Functions (UDF) and Stored Procedures.

Note: If you use a table-valued function just drop it in your dbml file and you will be able to access it like any other table.

Another approach is to use the a new recursive queries syntax (in the form of the WITH clause and Common Table Expressions-CTE) introduced in SQL Server 2005.

Take a look here: www.eggheadcafe.com/articles/sql_server_recursion_with_clause.asp

An approach of mixing CTE with Linq-To-SQL is presented here: stackoverflow.com/questions/584841/common-table-expression-cte-in-linq-to-sql