Home > English > Entity Framework Sorting by master then detail

Entity Framework Sorting by master then detail

As I get more and more comfortable with Entity Framework, I realize that there are some simple things within Linq2Sql that I absolutely miss. One of these features is the ability to Sort by a property in the underlying collection you are returning then by a property on a child collection as well.

This is easy with Linq2Sql, all I have to do is use the DataLoadOptions and embed a lambda expression that contains my order by expression. Once that is done, I can then pass the options the underlying LoadOptions property of the instance that I am working with and it is ready to go. This will provide me parent/child sorting capabilities.

There is another way that you can sort fairly easily in both Entity Framework and Linq2Sql but I personally don’t like it since most of my development uses Silverlight and WCF RIA Services. I like to get change tracking for free. This other way is to use projection when basically allows you to create a new anonymous type and return this new type with all of the sorting and flattening out if you need it. This approach is good for read-only screens or when you know that you need to denormalize your data across several entities and you are not concerned about losing the change tracking and have a mechanism for handling that yourself.

Now on to the way to get Parent/Child or Master/Detail sorting in the Entity Framework. Here is a sample Query that exposes a Customer object with its corresponding Order collection attached as well. The Customer object is also sorted by the CustomerName:

[Query()]
public IQueryable<Customer> ReturnCustomers()
{
    return this.ObjectContext.Customer
    .Include("Order")
    .OrderBy(x => x.CustomerName);

}

This satisfies the top level ordering but since the Order entity is a collection off of the Customer entity, I have no way to embed a Linq expression to force sorting the child record as well. I have tried using several different approaches but ultimately I believe this is a limitation with WCF RIA Services more than it is with Entity Framework.

I will now show you how I am facilitating the child detail level sorting on the client side of the application. First I am going to expose this newly created Query via a DomainDataSource. The following is a snippet of XAML showing all of the pieces working together:

<UserControl.Resources>
  <CollectionViewSource x:Name="cvsOrders" 
    Source="{Binding CurrentCustomer.Order}">
    <CollectionViewSource.SortDescriptions>
      <compMod:SortDescription PropertyName="OrderDate" 
        Direction="Ascending"/>
    </CollectionViewSource.SortDescriptions>
  </CollectionViewSource>
</UserControl.Resources>

<riaCtls:DomainDataSource x:Name="_ddsCustomers" 
    QueryName="ReturnCustomersQuery"
    DomainContext="{Binding DomainContext, Mode=TwoWay}">
</riaCtls:DomainDataSource>
<ListBox x:Name="lboCustomers"
    Grid.Column="0"
    ItemsSource="{Binding ElementName=_ddsCustomers, Path=Data}"
    SelectedItem="{Binding CurrentCustomer, Mode=TwoWay}">
</ListBox>
<toolkit:DataGrid x:Name="dgOrders"
    Grid.Column="1"
    ItemsSource="{Binding Source={StaticResource cvsOrders}}">
</toolkit:DataGrid>

Let’s start with the DomainDataSource first. As you can see, it is simply calling the Query that was created on the server. Next we see that we have a lbCustomers ListBox that sets the Data property of the DomainDataSource to its ItemsSource property. I am also setting the SelectedItem of the ListBox to the property exposed on my ViewModel called, “CurrentCustomer”. This allows me to access from other controls.

Note: The namespace alias compMod comes from the following mapping: xmlns:compMod=”clr-namespace:System.ComponentModel;assembly=System.Windows”

Finally, I have created a CollectionViewSource object. This may seem old hat to most WPF programmers and is a great addition to Silverlight as well. I set the Source property of the CollectionViewSource to the property I exposed on the ViewModel but I also reference the child collection of Order. I then add a SortDescription that sorts the Order collection based on the OrderDate property.

Now when this screen opens, it will be ordered by CustomerName first, then when a user selects a given Customer, all of the Orders will also be ordered by OrderDate as well.

This may seem to be a lot of work getting the Master/Detail or Parent/Child ordering to work but this solution turns out to be quite flexible and allows you to extend it to pretty much whatever you can think of.

Hope this helps….

Advertisements
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: