Friday, March 30, 2012

Cuckoo for POCO Puffs: Prequel

What exactly am I hoping to accomplish by moving to EF code-first or NHibernate?

The short answer is that I'm looking to gain features that I'd otherwise have to implement while at the same time simplifying and reducing the amount the code we already have.  For the benefit of getting my own thoughts in order I want to articulate a slightly longer answer which will inventory the features and identify the potential areas of simplification and reduction.

And that is what grieves me the most

We have a substantial codebase which utilizes our own class-in-charge patterned persistence ‘framework’, the bulk of which still works by using the Enterprise Library and manually mapping ADO.NET structures (datarows, datareaders, commands) back and forth to the database. This approach first started in the .NET 1.1 era. The framework mainly consists of a few base classes that provide more of a template (for consistency) than anything else. This approach has lasted a long time and continues to work. Nevertheless, there’s a certain amount of tedium and ceremony with our existing approach. For every domain object there are potentially the four classic (CRUD) stored procedures that must also be created, plus any other variations to provide alternative means of retrieval or persistence, and of course all the mapping logic. This can mean an explosion of stored procedures to meet a variety of query alternatives, or one procedure with a multitude of conditional switches executing different query versions based on parameter combinations. Invariably, to keep the number of procedures manageable, the same stored procedure is used to serve multiple purposes at the expense of efficiency.

Ah. It must’ve been when I was younger

Our active record pattern-ish approach leads to additional difficulties because its not well suited to treating complex graphs as aggregates, we often find ourselves in the eager vs. lazy load conundrums, validation is ad-hoc, concurrency is seldom handled, and as I've lamented caching is non-trivial. One of the more obvious cases where our framework struggles is the oft encountered situation where one use-case implies that domain objects would be more efficiently eager-loaded as an entire graph, while those same domain objects are more efficiently lazy-loaded within another use-case in a different module within the system.  The same is true of caching.

Its possible to evolve our framework, use code generation, and steal bits and pieces from other frameworks, and I’ve done a little of that. But that’s an awful lot of wheel inventing and plumbing.

My children, I have watched you for a thousand years.

For a long time now there have been frameworks that provide a much richer set of services, both at the domain layer and data layer (and some debate about whether these frameworks could or should serve both). The frameworks that I'm most aware of are Entity Framework, NHibernate, CLSA.NET and SharpArchitecture. Therefore, these are the focus of my re-evaluation. The features of each that I'm interested in are:

Entity Framework 4.3

  • Sql Generation
  • Linq support
  • Change Tracking
  • Validation facilities
  • Concurrency support


  • Sql Generation
  • Linq support
  • Change Tracking
  • Validation facilities
  • Concurrency support
  • Level 2 cache
  • Logging/tracing


  • Implementation of DDD
  • Loose coupling


  • Validation
  • Security
  • Transaction manager
  • Business Rules engine
  • Rich databinding support
  • N-level undo
  • aggregate roots
  • Mobile objects/portability

Infidel Defilers. They shall all drown in lakes of blood

Our first foray into the frameworks was EF v1, and that did not deliver on the promise of code reduction or simplicity. At best it was a wash, making simple things simpler and difficult things more difficult, mostly just pushing complexity around. That's likely partially the fault of our approach and partly that of the the agony of EF v1.  

I wish to speak to you now

With EF 4.3 code-first and FluentAPI we've taken a fresh look, and with its apparent similarities to Fluent Nhibernate it made sense to look at both.  I still like the idea of deploying changes and not having to deploy both code and SQL scripts simultaneously. Of course, the downside is that we can't change them independently. Oftentimes we’ve found it advantageous to be able to optimize SQL in a stored procedure and change it without having to recompile and redeploy an application. Some might suggest that we could get the best of both worlds by combining O/RM's with stored procedures (because they support this), but I feel like this is the worst of both worlds. By the way, I'm sorry but O/RM's don't generate more efficient code than I could write.  Nevertheless, generated SQL provides the opportunity to query the same objects differently in different parts of the application and get more appropriate SQL. This is even more true with column level change tracking.  Having code that is smart enough to only update what was changed rather than sending all values back and forth, as well as knowing when no update is necessary, would be a meaningful improvement.

This flame will burn away the darkness, burn you the way to paradise

Code that can easily be toggled between eager and lazy loading by use-case is certainly desirable. And having all the complexity of caching handled for me would be a dream come true.  That’s one of the more exciting differentiating features of NHibernate. But its not quite clear to me how well that works and whether we’d be able to reach a point where enough of the data access is managed by NHibernate to take advantage of Level 2 caching.

That is strength, boy! That is power!

Since 2005 I've been fascinated with CSLA.NET (although admittedly not fascinated enough to actually build something with it) and more so with each successive version. Its not an O/RM but it has some overlap in terms of the facilities it provides, like validation and change tracking. Additionally, it provides one specific advantage that I find particularly intriguing. The concept of mobile objects and with it a measure of portability. The ability to use the same business logic on both sides of RIA application, whether that be Silverlight, WPF, WP7, or even Monotouch and Monodroid is especially compelling. With the explosion of devices and platforms this is sounding more and more powerful.

Contemplate this on the tree of woe.

These frameworks are not mutually exclusive. We could use EF or NHibernate as both our data access and domain layer, or we could CLSA with EF or NHibernate, and SharpArchitecture already leverages NHibernate.  All this must be weighed against the time, effort, approach, and risk of switching. If the application(s) were to be built from scratch today, we'd clearly be using one or more of these, but alas I'm architecting after the fact. I have to deal with the knowledge that a migration is fraught with peril.

No comments:

Post a Comment