EF Persistence Ignorance Recap

I had someone email me a question today about POCO, IPOCO, persistence ignorance and the EF, and I responded to them with a summary of sorts which I thought might be helpful to some other folks, so I'm going to post it here as well. There's not a change in direction--just a further explanation of what we're doing--so if you've been following this topic for a while there won't be anything new for you, but maybe this will help other folks wade into the topic more easily when it comes up in the future. If after reading this, there are further questions, please don't hesitate to ask. I'd like to make sure that the message here is as clear as possible.

This whole space represents a continuum which looks something like this:

  • Persistence ignorance is the general term for how much knowledge the objects must have of the persistence layer. In this case we talk primarily about “complete persistence ignorance” which is a step further than POCO in the sense that you’d like to be able to say that you can create an assembly of domain objects where that assembly doesn’t have any reference to a persistence stack at all, and then just by adding a small amount of code/configuration on the outside you can persist those objects.
  • POCO is basically the idea of having plain CLR objects which do not have special requirements in order to work with a persistence stack like the EF. In practice this primarily talks about not requiring that the objects inherit from a particular base class and that they not be required to implement a particular interface. In many systems, though, you might say that they support POCO but still require something like attributes on the classes or other things in order to help convey some information to the persistence stack. The point, though, is that the domain objects don’t have to change substantively to support persistence so they are cleaner for remoting to other tiers, it’s easier to switch to another persistence stack at a later date, etc.
  • IPOCO is a subset of POCO which says that the objects don’t have to inherit from a particular base class but they either gain some benefit from implementing certain interfaces or may even be required to implement those interfaces.
  • Prescriptive classes or generated classes represent the other end of the spectrum. In these scenarios, the classes typically inherit from a particular base class which works directly with the persistence layer. In many cases the classes are auto-generated from a model of some kind and users can then extend them using partial classes or the like. Prescriptive classes have the disadvantage of being more tied to the persistence layer, but they tend to have advantages when it comes to performance as well as providing a broader set of services to the app developer that they would otherwise have to write themselves.

The EF started out as a framework which only supported prescriptive classes. Based on customer feedback we decided that it would be very important to support a greater degree of persistence ignorance for some scenarios, but we also believe that the prescriptive classes are great for other scenarios. So, we expect that overtime we’ll need to support this whole spectrum.

For the first release of the EF, we will support prescriptive classes and IPOCO. That is, you can have classes that do not inherit from our base class, but they must implement certain interfaces and they must have specific attributes in order to work with the EF. Right now there is a set of three interfaces, of which one is required (IEntityWithChangeTracker which is used for the object to communicate to the EF when the values of its properties are changed), one is required for any object which participates in persisted relationships (IEntityWithRelationships -- of course almost every object in a real system will participate in relationships so this one is pretty much also required), and one which is optional (IEntityWithKey – if you implement this then your object must have a property for storing the EntityKey, but in return parts of the system become faster/easier).

In future releases, we will work to make the remaining interfaces optional as well as to make it possible not to have any specific attributes on the classes but instead to specify all of that metadata in some other form outside the assembly containing the classes that will be persisted, but we were just unable to get all the way there in the first release.

No doubt a search of the web will turn up a variety of discussions on this topic, but here are a couple of my blog posts which provide some background reading in case you are interested:

- Danny