Cuckoo for POCO Puffs: Week 1

I completed converting my moderately complex sub-model (24 entities) from the database-first style to code-first style this week.  The results are pretty encouraging.

I find your lack of faith disturbing

The use of foreign key associations, POCO’s and the Fluent API vastly simplified the resulting code.  Not that I didn’t encounter my share of learning curve struggles.  The fluent api syntax for declaring relationships is a bit clumsy, and the difference between declaring properties as virtual or not and its resulting impact on lazy load behavior confused me on at least one occasion.  Notwithstanding those, the bulk of the effort was simply the brute typing involved in re-implementing all the class, repositories and relationships, as well as refactoring tests to use the new code. The EF 4.x POCO Entity Generator gave me a really good starting point, although it didn’t allow me to pick which tables, instead generating the whole database.

All too easy

What I found most compelling with POCOs, is that I no longer needed to jump through all the hoops to detach and re-attach object graphs.  You may recall we used this approach, Reattaching Entity Graphs with the Entity Framework, to handle this problem in EF v1.  Apparently, and it kind of makes sense with POCOs, that detaching and re-attaching is less of an issue.  My code-first repositories are so much simpler that I’m suspicious that either I’ve missed something or my chosen sub-model wasn’t sufficiently complex enough to surface the still lurking issues of detaching objects.  Then again, one thing I haven’t attempted yet is persisting a complex object graph as one unit, relationships and all.

Asteroids do not concern me

Once the object leaves the context its essentially detached.  One odd side-effect of this and lazy loading is that accessing a lazy property (even to check if its null) outside of the context results in an exception.  There doesn’t appear to be a good way to check if properties are loaded outside of the context.  To handle this I disabled lazy loading, which might seem extreme, except that I was already being explicit using Include(), and having EF attempt to lazy load detached objects doesn’t serve much purpose.

Another oddity I haven’t quite grokked is that foreign key associations don’t appear to stay in sync with their ID properties even after a SaveChanges() (e.g. if I update the StateId on an Address, the Address.State association doesn’t seem have the correct State after the persistence).  Its not a feature I’ve thus relied on so its not an issue in this case but something I’ll want to understand better if I go forward.

Impressive, most impressive

Overall, I’m very impressed with combination of code-first, POCO and the fluent api in EF 4.3.   I don’t see any reason not to convert our existing EF code to this approach, other than the time, effort and risk.  It may not be flawless, but it’s a considerable improvement over the contorted v1 style approach currently employed. There are two additional points of inspiration gleaned from this effort:

  1. The POCOs appear as if like they could just as easily work with NHibernate as with EF.  They have no dependency on or direct relationship with EF (thanks the the fluent api) and all the properties are virtual.
  2. There is a striking similarity between the POCO objects and our Domain objects in many cases,  In some cases, the POCO object is nearly identical to the Domain object that its hydrating.  This suggests to me that we may be able to collapse the two layers. 

Perhaps I can find new ways to motivate them

Next up I’m going to try to implement this same sub-model using the same POCO objects, but this time using Fluent NHibernate.  NHibernate is more mature, supports more databases, and has Level 2 cache support baked in.  All else being equal, NHibernate might be the better choice, so I want to see how equal all else is.

At some point I should probably explain what I’m trying to accomplish with all of this.

Comments

  1. Great article. Funny, as a developer with a few years of NH experience, I'm heading in the opposite direction (currently writing an EF provider for our framework). While NH has some great features and is mature, in my experience, if your DAL is LINQ heavy, you'll suffer in the translations of some of those queries.

    ReplyDelete
    Replies
    1. I forgot that you'd been using NHibernate for awhile. We should chat about it. So far I've found them to be very similiar. The primary NH feature I'm interested in Level 2 caching, but if there are other gotchas or poorer linq support that I haven't uncovered yet, lay them on me.

      Delete
  2. Unfortunately or fortunately, I don't have an intimate knowledge of the inner workings of NH. It has really just worked for the most part. We auto generate our hbm's based on our models, and from there it's pretty much set it and forget it. The only limitation I have seen personally is some LINQ queries that look good on paper (and in LINQ pad) don't translate that well (or at all). And I don't know much about HQL, but I really don't want to either. We've had to flatten out some pieces of our models into views for performance reasons. But the argument could be made that these are edge cases.

    ReplyDelete

Post a Comment

Popular posts from this blog

RIF Notes #4

RIF Notes #42

The greatest trick the AI ever pulled was convincing the world it wasn't THAT intelligent