Monday, August 9, 2010

Silverlight Neophyte 1: Include the Include Attribute

Summary
Use the Include attribute on related types that should be returned to the client.

RIA Services supposedly simplify and accelerate n-tier ASP.NET and Silverlight development. I don't have an opinion on the matter yet because I haven't finished my Silverlight 4 application yet. I think that I'm making good progress on my project for a Silverlight neophyte. That being said, I've spent a few too many hours on problems stemming from my Silverlight / RIA Services ignorance or poor or non-existent documentation. I'm sharing these gotchas as I encounter them.

I inherited a poorly designed legacy database that Entity Framework 4 nicely abstracts. Two of the tables, TableA and TableB, really should be a single table because they merely partition a single, cohesive set of data into two different, um, parts. There are several legacy applications that operate against TableA and TableB or this design would have been changed years ago. I've created a couple of views that nicely unify the tables, and these views work well for read operations.

My Silverlight application needs to edit these tables, and that requirement is where today's topic originates. As you expect, my entity model contains types that represent TableA and TableB, and each of these types (EntityTypeA and EntityTypeB) have navigation properties related to the other type. With that in mind, I added a new method to my domain service that returned a single EntityTypeA. My thinking was that I could then use the navigation property value (EntityTypeA.EntityTypeB) to get the complete set of data.

So no big deal here. My ViewModel called the DomainContext.Load method and I got back an instance of EntityTypeA. But EntityTypeB was null. OK, I thought, I've probably not configured the loading operations properly, I'll set ObjectContext.ContextOptions.LazyLoadingEnabled = false and everything will be alright. Nope, still a null EntityTypeB. I must have done something else wrong. Fine, I'll change my query from

EntityTypeA entityA = this.ObjectContext.EntityTypeA.Include("EntityTypeB").FirstOrDefault(oo => oo.ID == Id);
to
EntityTypeA entityA = this.ObjectContext.EntityTypeA.FirstOrDefault(oo => oo.ID == Id);
if (!entityA.EntityTypeBReference.IsLoaded)
entityA.EntityTypeBReference.Load();


Still no related entity, and I could see that the property was getting successfully set on the server. It just wasn't making it back to the client.

I was able to finally conjure the correct Google search incantation and found Vincent Leung's post regarding the Include attribute. As soon as I set that in EntityTypeA's DomainService metadata class on the EntityTypeB property my problem was solved. I was able to change my code back to the following more concise format:

EntityTypeA entityA = this.ObjectContext.EntityTypeA.Include("EntityTypeB").FirstOrDefault(oo => oo.ID == Id);

That is all.

Google query

RIA Services Reference

No comments:

Post a Comment