Sep 21, 2011

Regaining Automatic Relationship Fix-Up with DbContext POCO Entities

Recently at work I upgraded the WPF application project I've been working on for a few months now to Entity Framework 4.1 so that we could take advantage of the new DbContext class. It was a snap using NuGet, too. When we started, we used database-first and then generated POCO classes via the Entity Framework POCO Generator extension plugin.

I quickly noticed some problems in our application, though. Many of the method names are different between ObjectContext and DbContext, so it required a small bit of refactoring. I didn't have any problems with this, so I didn't suspect anything, but suddenly navigation properties were coming back null when they used to not be. We've got lazy-loading disabled (because we explicitly make data loading calls on asynchronous Tasks), but I was used to navigation properties being filled whenever its associated foreign key integer value changed, provided the associated object was already cached in the context.

Specifically, we have a Status entity type that maps to a lookup table on the data source. Our main objects maintain a foreign key to this as well as a direct entity navigation property. Something like the following:

class Invoice
{
    public int InvoiceStatusId { get; set; }
    public InvoiceStatus InvoiceStatus { get; set; }
}

class InvoiceStatus
{
    public int InvoiceStatusId { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
}

This is a simplified example, but essentially it allows us to have the description displayed in a ToolTip or something to further explain various statuses. We've got a form that lets users change said status value to something else. This is done by simply changing the StatusId value ultimately, which due to the automatic POCO smartness changed the associated Status value to the correct entity as well, since we'd have all possible Status objects cached in the context already. Or rather, it used to.

Turns out the original POCO generator was much more complicated than the one that ships with the new DbContext POCO Generator templates. I've since read that this is due to the DbContext stuff, naturally, being geared to the new code-first support. As a result, it is far more light-weight.

Well, I didn't want to lose the relationship fix-up logic but we definitely wanted to keep the DbContext (the Local property on DbSets is turning out to be quite useful). I ended up combining the Context T4 from the new DbContext POCO Generator with the Entities T4 from the old POCO Generator. After a few days of testing it out everything seems to work fine and we get the best of both worlds.

5 comments:

  1. Could you explain in greater detail exactly what you did with the T4? I'm having a similar problem.

    ReplyDelete
    Replies
    1. When you right-click in your Entity Model and choose "Add code generation item" and pick your POCO generator, you'll see it adds two separate .tt files to your project. One is named .tt and the other .Context.tt

      I selected the DbContext POCO Generator, since I wanted to shift to DbContext instead of ObjectContext. I kept the Context.tt file it put in there, which generates a DbContext class from the model, but I removed the other .tt file, the one that generates the actual POCO entity classes. In my case, I simply restored from source control, the original POCO entity classes .tt file which had been added months ago when we initially started with the regular POCO Generator. They seem to work fine mixed together and we've not had any problems since.

      Delete
  2. Hi Sean

    Could you perhaps post the tt file that you used?

    Many thanks

    ReplyDelete
  3. Would really appreaciate a copy of your tt too

    ReplyDelete
  4. Would really appreaciate a copy of your tt too

    ReplyDelete