Binding Many to Many relationships using nested repeaters with LINQ by ThinqLinq

Binding Many to Many relationships using nested repeaters with LINQ

Last time, we looked at the structure of the ThinqLinq posting items to see how we could extend the RSS feed limiting the output by categories. This time, we are going to look at extending the standard post output on the site to display the categories for each post. When we set categories and posts up, we created a many-to-many relationship between the posts and categories using an intermediary CategoryPost table and object collections.

When dealing with many to many relationships with object hierarchies in LINQ to SQL, we are really looking at a one to many to one rather than a true many to many. That is because we typically will start with a single object and drill to it's children, not caring if other objects are also parents to those same children. Since we are essentially dealing with a standard one to many relationship with an extended object, we can use the same databinding capabilities that we would for parent child relationships in ASP grids.

When creating ThinqLinq, we decided to use the Asp:Repeater control to layout the posts. The basic structure for displaying posts is as follows:

<asp:Repeater ID="PostRepeater" runat="server" EnableViewState="False">
 
<ItemTemplate>
   
<div class="post"><h2><%#Eval("Title")%></a></h2>
   
<div class="story"><%#Eval("Description")%></div>
   
<div class="meta">Posted on <%#Eval("PublicationDate")%></div>
  </ItemTemplate>
</
asp:Repeater>

To add the categories, we will want to iterate over the contained CategoryPosts collection that the PostItem exposes. Binding a collection to a grid is as simple as binding any other property to a label. If we want to add the categories using a repeater, we can add the repeater before the end of the ItemTemplate as follows:

<asp:Repeater ID="PostRepeater" runat="server" EnableViewState="False">
 
<ItemTemplate>
     <!-- Bind post info -->
    
<

asp:Repeater ID="Categories" runat="server"
                           
DataSource='<%# Eval("CategoryPosts") %>'>
   
</asp:Repeater>
  </ItemTemplate>
</asp:Repeater>

Notice, here we can nest a repeater inside a main repeater. As each item is evaluated, its corresponding child collections will in turn be evaluated because we have set the datasource of the contained repeater to a collection property of the parent object.

So now that we can access the child objects that are in the intermediary many-to-many table, how do we access their children? Remember in this case the children (Category) are in a one-to one relationship with their parent (CategoryPost). If we were to bind using the Eval statement at this point, we would reference the CategoryPost object. To access the description in the Category, we simply do an Eval on the categoryPost object to its contained Category object and then reference the resulting Title. Here's the statement we will use to bind to the category's title:  <%# Eval("Category").Title %>. Remember here, Category in this case is a property of CategoryPost. With this in mind, here's the code to bind the categories separating each with a comma.

<asp:Repeater ID="PostRepeater" runat="server" EnableViewState="False">
 
<ItemTemplate>
   
<div class="post"><h2><%#Eval("Title")%></a></h2>
   
<div class="story"><%#Eval("Description")%></div>
   
<div class="meta">Posted on <%#Eval("PublicationDate")%></div>
   
<asp:Repeater ID="Categories" runat="server"
                          
DataSource='<%# Eval("CategoryPosts") %>'>
      
<HeaderTemplate>Categories:</HeaderTemplate>
      
<ItemTemplate><%# Eval("Category").Title %></ItemTemplate>
      
<SeparatorTemplate>, </SeparatorTemplate>
    
</asp:Repeater>
  </ItemTemplate>
</
asp:Repeater>

Posted on - Comment
Categories: LINQ -
comments powered by Disqus