Jon
Jon

Reputation: 40032

Hierarchical Database Driven Menu in MVC

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 hierarchies 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 Hierarchy 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 hierarchy. 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;


}

Upvotes: 1

Views: 2463

Answers (3)

thanassis
thanassis

Reputation:

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

Upvotes: 0

Drevak
Drevak

Reputation: 867

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)

Upvotes: 0

user1151
user1151

Reputation:

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 :)

Upvotes: 1

Related Questions