Persistence Ignorance: OK, I think I get it now.


Let me apologize up front for how long it has taken me to get back to this topic.  What I can say, though, is that in the intervening interval I have devoted real time to studying agile design principles and domain driven design.


Initially I thought that some of the requests for *complete* persistence ignorance were the products just of dogma rather than fully informed and reasoned arguments, but when so many people give such passionate feedback it was clear that I needed to investigate more before I could claim to have any sort of an informed opinion.  The product of my research is that I am now truly convinced of the importance of complete persistence ignorance for some scenarios.  As a result, the team is now working on a series of product changes aimed at ensuring that a later move to complete persistence ignorance will not be a fundamental breaking change. 


There’s no question, though, that complete persistence ignorance comes at a price–both in the performance of applications built with “pure POCO”, persistence ignorant domain models and as a result in the complexity of the entity framework which enables them.  The additional complexity of the framework is not just about enabling such applications to function but a product of the fact that the performance degradation which results means that the framework must support a spectrum of flexible options between complete persistence ignorance on one hand and prescriptive architectures which build some persistence information into the domain model to improve performance on the other hand.


To make this more concrete, we have identified 4 elements of the existing entity framework design which block persistence ignorance.  That is, 4 ways in which entities are currently required to have knowledge of the framework:



  1. They must store a copy of an EntityKey.

  2. They must provide change tracking notifications through a prescriptive interface.

  3. They must be decorated with a series of attributes which provide additional metadata.

  4. If they participate in relationships, the requirements are even more stringent as indicated by the requirement to implement the interface IEntityWithRelationships.

The first two requirements are enforced with the IEntity interface and must be addressed if we are to enable persistence ignorance at any point in the future.  In fact a series of key object services APIs currently .  At the same time each of these has significant performance implications.  Choosing not to store EntityKeys on the entities, for instance, means that navigating from an entity to the ObjectStateEntry which matches it either requires a brute-force search of the ObjectStateManager or for the ObjectStateManager to maintain a dictionary mapping from CLR reference to ObjectStateEntry which is a significnat expense.  Not supporting the change tracking mechanism means that the ObjectStateManager must cache a copy of the original values for each entity (all original values and they must be cache whether or not the entity is modified).


While I do believe that there are circumstances in which the loss of performance is a reasonable tradeoff for persistence ignorance, I also believe that for a great many applications, even where persistence ignorance is highly valued, there will come a time in the performance tuning process when one or another of these two compromises must be made.  As a result, we are working on replacing IEntity with two separate interfaces and making both of them optional–which means the object services API signatures will change from taking parameters of type IEntity to type “object” and the framework must support multiple mechanisms for each of these.


The 3rd and 4th issues are, on the one hand, harder to correct, but on the other hand things which can be corrected later.  At some point we will add an alternative mechanism for specifying metadata about the entity objects (thus freeing us from the hard requirement for attributes).  Similarly, we can envision ways to enable POCO collection and reference mechanisms for relationships which can be added later as a complement to the existing prescriptive EntityCollection<T>, EntityReference<T> and RelationshipManager classes.


So, to sum it all up, message received: persistance ignorance is needed, and we’re now working to deliver it.  The first release of the entity framework likely will not have full support for it (there’s just not enough time), but we will work to get into the first release the key changes which could not be made later so that the stage is set for the next release.


– Danny


 

Comments (9)

  1. Garry Trinder says:

    First of all, that’s great to hear.

    Second, the context for persistence ignorance is the Domain Model pattern – I’ve got a write up about it here:

    http://udidahan.weblogs.us/2007/04/21/domain-model-pattern/

    That object model should be independent of UI concerns as well. The same goes for how the data in it get sent across the wire.

    By keeping it isolated, we make it that much more testable. Since our complex business logic is embodied in it, we’re really going to need to know if some change we made broke other assumptions.

    That said, these concerns will definitely affect the way we design the domain model.

  2. rogerj says:

    Danny,

    Pingback from http://oakleafblog.blogspot.com/2007/06/entity-framework-updates.html

    and thanks for the heads-up.

    –rj

  3. simmdan says:

    Yes, Udi, I have been spending a lot of time thinking about domain models, domain driven design and the like.  And yes, certainly it makes sense to isolate the domain model from other concerns.  We have been working for some time to isolate domain models from UI and to make reasonable patterns for remoting them without having an impact on the model.  The question about persistence gets a bit interesting, though, given that often business logic needs to interact with some sort of persistence abstraction in order to retrieve or manipulate related domain objects.  I’ve known all along that there’s huge value in isolating the domain model from changes to the database (that’s one of the great advantages of a system like the EF where you can refactor your database, change the mapping and keep your domain objects unmodified).  What I didn’t understand until recently was just how *completely* isolated it was important to make the domain model in some situations.  In fact if you look at a variety of the popular literature on this topic, not everyone believes in total isolation (attributes can be a reasonable tradeoff, for instance, because they are relatively unintrusive, etc.).

    In any case, we’re now working to create a framework which enables a range of options so that you can be completely ignorant or you can bake various amounts of presistence awareness into your domain objects depending upon the needs of your particular situation.

    I would also assert that nothing about the EF should prevent you from employing any of the techniques which you would normally use to achieve separation from UI or remoting/messaging.

    – Danny

  4. Persistence Ignorance in the Entity Framework

  5. Garry Trinder says:

    "The question about persistence gets a bit interesting, though, given that often business logic needs to interact with some sort of persistence abstraction in order to retrieve or manipulate related domain objects."

    The logic within the Domain Model just navigates the object graph for retrieval, and calls methods (which change the object’s internal data) in order to manipulate those domain objects.

    In the case of improving the performance of object retrieval, you’ll want a way to ask for an entire sub-graph to be loaded in a single database hit, rather than having objects loaded on demand as you navigate the graph. I’ve got a post up showing a design that clearly separates out the concern of defining object-graph retrieval here:

    http://udidahan.weblogs.us/2007/04/23/fetching-strategy-design/

    I’ve got another post up on showing different styles of having the domain model communicate out persistence demands to the Service Layer, which actually calls the "persistence abstraction". Take a look and tell me what you think:

    http://udidahan.weblogs.us/2007/06/04/performant-and-explicit-domain-models/

  6. BenScheirman says:

    I’m really pleased to hear this.  I never did chime in publicly on the debate, but I’m firm with the PI folks.

    But, as you say, there are cases when Persistence Aware objects give you a lot of benefits.  We just want to be given the flexibility to choose.

    Also, the most effective way that I have found to flesh out a good domain model is to actually write it test-first (for me, anyway).  If that meant that I had to create a table (or tables) and setup connection information, then I’m going against the grain.  The PI approach will allow me to worry about persistence once the domain model has settled some, so there isn’t any wasted effort in mapping to the database so early on.

  7. I had someone email me a question today about POCO, IPOCO, persistence ignorance and the EF, and I responded

  8. BlogCoward says:

    ADO.NET Entity Framework Vote of No Confidence

  9. naranjandev says:

    We certainly acknowledge the concern on persistance ignorance,with reference field.We only expand our wisdom by acknowledging The ignorance.

Skip to main content