3

I am developing an application using WPF/MVVM. I have a WCF data service project which provides operations for retrieving data from an ADO.NET data model using entity framework. I then have a wpf client which binds to viewmodel properties that fetch from the WCF service. The scenario involves clients/offices. The client entity has a navigation property of type office, as is implemented as a foreign key in the database. The problem is that when my viewmodel gets the list of clients from the data service, the navigation property is null. The service operation however does retrieve this information.

WCF Service Operation

[OperationContract]
public IEnumerable<Client> GetClientsByOffice(int officeID)
{
    using (var context = new LDC_Entities())
    {
        var result = context.Clients.Include("Registered_Office")
            .Where(c => c.Registered_Office_ID == officeID).ToList();

        result.ForEach(c => context.Detach(c));
        return result;
    }
}

As you can see the office property is loaded within the context query. If I put a breakpoint in at this point, the result variable holds the clients information, and the navigation property is also filled as expected.

WPF ViewModel

private void RefreshClients()
{
    serviceClient.GetClientsByOfficeCompleted += (s, e) =>
    {
            Clients = e.Result;
            foreach (Client c in Clients)
                MessageBox.Show(c.Office.City);
    };

    this.serviceClient.GetClientsByOfficeAsync(CurrentOffice.Office_ID);
}

If I inspect the Clients property after this method is called, the navigation property is now empty, and as such the message box call I put in throws a null pointer exception. It appears that as it comes through the WCF service, it drops the navigation properties of the client objects.

Please could anyone explain how this information can be retained when making this call?

Many thanks in advance, Mike

Mike Scott
  • 153
  • 1
  • 3
  • 12

1 Answers1

1

As you can see the office property is loaded within the context query. If I put a breakpoint in at this point, the result variable holds the clients information, and the navigation property is also filled as expected.

I'm not sure which point you're talking about, as there are multiple lines of code there. But the object graph gets shredded when you detach entities.

The solution presented in that question is to use a NoTracking query so you don't have to detach:

using (var context = new LDC_Entities())
{
    context.Job.MergeOption = MergeOption.NoTracking;
    return context.Clients.Include("Registered_Office")
        .Where(c => c.Registered_Office_ID == officeID)
        .ToList();
}

This solution will probably work better for you than it did in that question because they also needed to do an update, which requires object tracking, whereas you're just doing a query.

Another way to solve this is to avoid exposing the classes from your data persistence layer to higher level layers. Then you don't have to worry about things like how entities serialize, as you only work with them when working directly with the data persistence layer. This also gives other advantages, like looser coupling between layers, and exposing less unnecessary data to higher level layers. Using a library like AutoMapper can help reduce some of the boilerplate of copying data between layers.

Community
  • 1
  • 1
Merlyn Morgan-Graham
  • 58,163
  • 16
  • 128
  • 183
  • Fantastic, this answered my question fully and it is now working as intended. Thanks for your clear explanation and apologies I was not aware of what the "object graph" was so could not find other solutions. Thanks for the recommendation of alternate techniques and a redefined architecture, will consider that for the future. Thanks again – Mike Scott Dec 06 '11 at 11:31
  • @MikeScott: NP, that's what we're all here for :) I think "Navigation Property" is more commonly used when talking about the EF, and will be more searchable for people with the same problem. As for redoing your architecture, I recommend doing what is cheapest and easiest until you start hitting walls too often, or your architecture starts looking to warty. – Merlyn Morgan-Graham Dec 06 '11 at 11:39