A: 

I have recently been using the "ADO .Net Entity Data Model" template to control connectivity to a MSSQL database that supports hierarchy data and it has been working well.

You can just tie your presentation layer directly to the data models.

If your keys are set correctly in the database its a snap to get up and running..I think it also requires ADO.Net 3.5

Creating ADO.NET Entity Framework Entity

MS information on entity

Jay
Unfortunately we have to stick with the technology stack we are currently using. I need to do as I said in my question, construct an intermmediate ViewModel object and pass this on to my view.
KingNestor
+1  A: 

Just store a List instance in your view data?

public class Agency
{
   public List<BusinessUnit> Units;
   public string Name;
   public int NumberOfAccounts
   {
      get 
      {
         int ret = 0;
         foreach(BusinessUnit unit in units)
            ret += unit.NumberOfAccounts;
         return ret;
      }
   }
   // ... continue this strategy for other properties
}
public class BusinessUnit
{
   public List<Client> clients;
   public string Name;
   public int NumberOfAccounts
   {
      get 
      {
         int ret = 0;
         foreach(Client client in clients)
            ret += client.NumberOfAccounts;
         return ret;
      }
   }
   // ... continue this strategy for other properties

}
public class Client
{
   public string Name;
   public int NumberOfAccounts;
}
Spencer Ruport
A: 

Assuming that your Linq2Sql implementation has the same relationships in it as the database (which if you did drag and drop to the designer, they definitely do), here's how I would approach it.

I would create a strongly typed partial view of type Agency that would represent each section (Agency, in your case), call it AgencyReportSection.ascx. This control will take an agency, iterate through its business units, which in turn iterate through its clients.

Wherever you are packaging up your data, do something like this:

DataContext context = new DataContext();
DataLoadOptions options = new DataLoadOptions();
options.LoadWith<Agency>(a => a.BusinessUnit);
options.LoadWith<BusinessUnit>(b => b.Client); 

context.LoadOptions = options;

What this will give you is that when the context gets an agency, it will follow the defined relationships and give you those objects as well. So you get:

Agency a = context.Agency.FirstOrDefault();
IEnumerable<BusinessUnit> units = a.BusinessUnits;
IEnumerable<Client> clients = units.Clients;

Your view could do something like:

<% foreach(var agency in agencies)%{>
<% Html.RenderPartial("AgencyReportSection"); %> 
<%}%>

The reason you are doing the data load option is to avoid lazy loading in the view, let the model pack up all the necessary data.

I hope I've understood your question correctly...

KevDog