Mike Scott
Mike Scott

Reputation: 153

Navigation Property Being Lost?

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

Upvotes: 3

Views: 1385

Answers (1)

Merlyn Morgan-Graham
Merlyn Morgan-Graham

Reputation: 59131

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.

Upvotes: 1

Related Questions