If you have the appropriate relationships set up in the database (and therefore, in the DBML), you may want to consider something like this (UNTESTED):
<table>
<tr>
<asp:Repeater ID="_users" runat="server">
<ItemTemplate>
<td><%# Eval("UserName") %></td>
</ItemTemplate>
</asp:Repeater>
</tr>
<asp:Repeater ID="_products" runat="server">
<ItemTemplate>
<tr>
<td><%# Eval("Product.ProductName") %></td>
<asp:Repeater ID="_users" runat="server" DataSource='<%# GetUsersProducts(Eval("ProductID")) %>'>
<ItemTemplate>
<td><%# Eval("count") %></td>
</ItemTemplate>
</asp:Repeater>
</ItemTemplate>
</asp:Repeater>
</table>
Code-behind:
protected void Page_Load(object sender, EventArgs e)
{
_users.DataSource = context.Users.OrderBy(u => u.UserName);
_users.DataBind();
_products.DataSource = context.Products;
_products.DataBind();
}
protected object GetUsersProducts(string ProductID)
{
var prodord = from op in context.OrderProducts where op.ProductID == ProductID select op;
return from u in context.Users.OrderBy(u2 => u2.UserName) select new {
count = prodord.Where(op => op.Order.User.UserID == u.UserID).Sum(op => op.ProductQty)
};
}
You will obviously want to change around your markup and some of the object types, but I'm hoping this will get you going. I try to use the autogenerated class object structure as much as possible to avoid creating unreadable LINQ queries.