6

Possible Duplicate:
What are the benefits of Persistence Ignorance?

After some time and some questions trying to figure out the entity framework, I've come to the conclusion that I just don't get what the point of persistence ignorant objects is.

As best as I can tell, the practical difference between using persistence-aware objects and persistance-ignorant ones is that one gets used something like

Person p = Person.Load(id);
p.Active = false;
p.Save();

and the other is used along the lines of

using (var context = new MyContext())
{
   Person p = context.Persons.Single(x => x.ID == id);
   p.Active = false;
   context.SaveChanges();
}

In the first case, I can return p, and call Save() at some later point. In the latter, I could return p, but I'd need to put it into a new MyContext() to save it. In the first case, assuming that Person inherits Load() and Save() from some base object which actually handles the database logic, if I wanted to change the persistence, it would just involve changing that base object (or even just have an IPersistent interface which multiple base classes can implement to access multiple stores). In the latter, I would need to change every instance of MyContext if the persistence layer changed, and it would be hideously complicated to do piecemeal.

My impression is that persistence-ignorance is a good thing. I just can't understand why. It seems like it's much more complicated to set up, work with, change wholesale and change piecemeal, with no advantage for that complication. Am I just missing something important, or is my entire understanding of what persistence-aware/ignorant means flawed?

Community
  • 1
  • 1
Bobson
  • 13,498
  • 5
  • 55
  • 80
  • In addition to persistence ignorant entities, you should also abstract away your ORM. A common method of doing so is the [Repository pattern](http://martinfowler.com/eaaCatalog/repository.html). – jrummell Jun 18 '12 at 14:05
  • @DavidHall, I don't think it's a duplicate. At least, after reading the answers on the other question I still don't see why a *properly abstracted* persistence aware object is better than a persistence ignorant one. – Bobson Jun 18 '12 at 14:11

2 Answers2

5

Persistance Ignorance is part of Seperation of Concerns. You should ask yourself, why should Person know how it should be loaded or saved? Person should deal with its own little domain.

PI means that Person doesn't care if it comes from memory, SQL, flat binary or any other means of Persistance and allows you at later point to replace your persistance layer to something else. You might initially develop your application to use flat binary files with the basic serializers to store data. Later, you might upgrade to SQL for performance reasons-- and this change is only needed in the one location whose -job- it is to handle persistance, the associated layer/component. Otherwise you must go through your entire code base to change little parts here and there that deal with persistance.

David Hall
  • 32,624
  • 10
  • 90
  • 127
Jaapjan
  • 3,365
  • 21
  • 25
  • See, my experience has been exactly the opposite. A Person object that inherits from a base type that knows about persistence is trivial to change to a new persistence layer, but a PI Person object is kindof a pain to alter. I certainly won't claim that an Aware object is better if every single object has to have its own *separate* knowledge of how to access its data, but so long as you can abstract it into a single place, I can't see how PI is better. – Bobson Jun 18 '12 at 14:06
1

Just to speak about your example, by writing Person.Load(id) you're saying - load this object by looking at his identifier - you're creating a rigid factory pattern, by wich you can only get objects if you know their ID, later you'll find out that you need to extract records based on some search criteria, and you'll add more factory methods whereas the second solution already gives you all the freedom you need.

The second solution is perfect to switch the persistence logic at runtime, since it is decoupled from the object model, you could theorically decide wich persistence engine to use inside your client code, without hardcoding and touching your OM, and it's false to say you would need to change every instance of MyContext, you should write your client code to let it receive the context from a sort of factory class or dependency injection.

As an example you could have this pseudocode:

var person = onlineDbContext.Persons.Single(x=>x.Guid == myguid);

offlineDbContext.Persons.Add(person)
offlineDbContest.SaveOrUpdate();
Spartaco
  • 459
  • 5
  • 7
  • Would that pseudocode have to be inside two separate `using()` statements, one for each context? Also, how can I have multiple contexts that support the same object? – Bobson Jun 18 '12 at 14:58
  • I didn't write the using statements because it doesn't matter, I'm not even talking about a specific ORM, I just showed that if you separate the data by the way it is handled, like in the letter from the postman, you get more opportunities. How to create a different postman is another subject. – Spartaco Jun 18 '12 at 15:18
  • Fair enough. However, I still have no idea how to use `person` in a different context. Having a different postman doesn't help if the new postman is on a different route and never visits my place. This answer seems to be exactly what I'm looking for, I'm just trying to understand it. – Bobson Jun 18 '12 at 15:27