Does NH really have Persistence Ignorance with POCOs? (Proxies question)

19 views
Skip to first unread message

MAMMON

unread,
Oct 7, 2008, 3:55:58 PM10/7/08
to nhusers
Lately I've been thinking about Persistence Ignorance. In the past, I
don't know if I ever procured a formal definition of the term. It
always seemed to make sense in the context it was used. My contextual
definition has historically been something like "The UI layer
shouldn't have to know or care what OR/M or other technology I'm using
to store and retrieve data", a la Separation of Concerns. I shouldn't
have any "using" directives for NHibernate namespaces in ANY of my UI
code.

With a lot of Entity Framework buzz being generated recently, due to
it's v1 release with VS2008 SP1, the term Persistence Ignorance has
been climbing the Google ranks ladder. Indeed, a Google search of the
term shows that of the top 5 results, 3 are about the Entity
Framework. Since I work in an otherwise all Microsoft shop, I am very
interested in the EF, and the recent buzz has caused me to think more
about Persistence Ignorance. Out of the box, EF doesn't have it, but
someone at MS has created a PI POCO adapter for EF v1.

http://blogs.msdn.com/jkowalski/archive/2008/09/09/persistence-ignorance-poco-adapter-for-entity-framework-v1.aspx

That article made me think of PI in a new way: not only should the UI
layer, or any other consuming layer, not have to know or care what OR/
M or other technology I'm using, but my classes should be able to be
POCOs, and I shouldn't have to make them jump through hoops in order
to be functional and "persistable". EF v1 (without the mentioned POCO
adapter) requires that classes are derived from EntityObject.
NHibernate is nice because there is no such requirement. However, I'm
not sure NHibernate is really Persistent Ignorant. It might not force
me to use dependent base classes, causing tight coupling, but it DOES:
+ Force me to make all of my methods and properties virtual, for the
use of proxies
+ Force me to override Equals() and GetHashCode(), because of proxies
+ Prevent me from putting logic in public property getters/setters,
because the proxies, upon hydrating objects, would incorrectly execute
that logic.
+ Create the "polymorphic databinding" problem with lists and
collections of objects, because of proxies.

What specifically got me on this train of thought was this problem:

public class Person
{
private string _fname;
private DateTime _dateLastModified;

public virtual string FName
{
get { return _fname; }
set
{
_dateLastModified = DateTime.Now; // Problem here
_fname = value;
}
}
}

With business rules inlined in the logic in the FName setter, won't
lazy loaded instances of Person call the setter to lazily hydrate the
instance? And wouldn't that cause the _dateLastModified value to
change, even though no real modification has been made?

So does NH really achieve Persistence Ignorance?

(PS, I'm not trying to be negative here, so let's not get the flame
throwers out just yet)

Ayende Rahien

unread,
Oct 7, 2008, 4:03:45 PM10/7/08
to nhu...@googlegroups.com
There is nothing in NHibernate that demands that you would use the DynamicProxy support.
NHibernate's proxies are pluggable, just build your own if it bothers you.

Greg Young

unread,
Oct 7, 2008, 4:06:22 PM10/7/08
to nhu...@googlegroups.com
PI has always been defined as the domain not having any changes in
specific for it persistence mechanism.

I believe we can give credit to Jimmy Nilsson for creating in the term
in ADDDP (Applying Domain Driven Design and Patterns).

You could use nhibernate in a more classic repository implementation
(DAO layer) and not run into these issue with your proxies.


There are many other issues with nhibernate and PI ... my personal
largest one is the lack of support for constructor mapping which can
really screw with validation stories but again I can work around this
in the same way I can with EF, I can use DAOs and put a repository
over the top of them.

Cheers,

Greg

--
It is the mark of an educated mind to be able to entertain a thought
without accepting it.

Ayende Rahien

unread,
Oct 7, 2008, 4:08:58 PM10/7/08
to nhu...@googlegroups.com
Greg,
IInterceptor.Instansiate ?

Greg Young

unread,
Oct 7, 2008, 4:13:17 PM10/7/08
to nhu...@googlegroups.com
Let me clarify, it supports it. It's just very painful in implementation...

Ayende Rahien

unread,
Oct 7, 2008, 4:18:28 PM10/7/08
to nhu...@googlegroups.com
Patch it to make it work better for your scenarios. That tends to be easier than just living with awkwardnss.

MAMMON

unread,
Oct 7, 2008, 4:20:19 PM10/7/08
to nhusers
"Write your own" is never a very good answer. I know I was bringing
up a touchy subject, but was hoping to avoid defensive answers. I
like the performance the proxies give me, and I like the support for
lazy loading, but that doesn't mean there aren't restrictions and
shortcomings.

I actually did create an implementation of IInterceptor to test it
out, and to fix a different potential problem I'm facing with this
application, but there are quite a few methods in there that haven't
been in past version. This means that 1.2 examples don't show me all
the methods. I'm not sure what all the methods do, and I haven't
found many examples, or any documentation. Some of the methods return
an object, and in those cases, it seems that to NOT intercept, you
just return null. Others, however, return bool, and it's not clear to
me when I should return true and when I should return false in order
to NOT intercept. Is there documentation on this somewhere, or a NH
2.0 example I can see?

Thanks for the quick responses and good advice.

On Oct 7, 1:13 pm, "Greg Young" <gregoryyou...@gmail.com> wrote:
> Let me clarify, it supports it. It's just very painful in implementation...
> On 10/7/08, Ayende Rahien <aye...@ayende.com> wrote:
>
>
>
> > Greg,
> > IInterceptor.Instansiate ?
>
> >>http://blogs.msdn.com/jkowalski/archive/2008/09/09/persistence-ignora...

Ayende Rahien

unread,
Oct 7, 2008, 4:27:11 PM10/7/08
to nhu...@googlegroups.com
You can selectively intercept by using EmptyInterceptor as a base class, which will also deal with the default behavior appropriately.

That was not a defensive answer, by the way, that was an expression of intent. If you don't like it, fix it.
The source is there, and the architecture supports it.

MAMMON

unread,
Oct 7, 2008, 4:35:09 PM10/7/08
to nhusers
The EmptyInterceptor is exactly what I needed. This is excellent, now
I can get all that auditing in there that I want. Thanks!

Roger Kratz

unread,
Oct 7, 2008, 4:57:37 PM10/7/08
to nhu...@googlegroups.com
Just a few notes...

<<Force me to make all of my methods and properties virtual, for the
use of proxies>>
Let the proxies be created by deriving from an interface instead. <class proxy="yourInterface">

<< public virtual string FName
{
get { return _fname; }
set
{
_dateLastModified = DateTime.Now; // Problem here
_fname = value;
}
}>>
Map fields instead of properties.

I'm not saying this is the way to go, but it solves these issues.

/Roger


________________________________________
Från: nhu...@googlegroups.com [nhu...@googlegroups.com] f&#246;r MAMMON [die...@gmail.com]
Skickat: den 7 oktober 2008 21:55
Till: nhusers
Ämne: [nhusers] Does NH really have Persistence Ignorance with POCOs? (Proxies question)

Stefan Nobis

unread,
Oct 7, 2008, 5:17:14 PM10/7/08
to nhu...@googlegroups.com
MAMMON <die...@gmail.com> writes:

> So does NH really achieve Persistence Ignorance?

IMNSHO it's a dumb idea to try to make your business layer completly
persistence ingnorant (in the way you suggest), because there is some
persistence in the background and you are developing a complex
system. Having really pure POCOs with absolut none constraints, where
you program as if no persitence exists, is like having a team of
a hundred developers writing code with no constraints (at least no
coding conventions) and hoping all will be well, working, and good
looking in the end.

Complex systems needs decisions and constraints and conventions. There
are very important. And especially the heart of your system is
influenced by these decisions and constraints. Deal with it!

The crucial idea of presistence ignorance is to try to help to make
clear decisions. You should not use NHibernate and ISessions all over
your code -- but this is not because otherwise it would be so easy to
exchange your ORM (it never is), but because you need this to better
structure your software, because otherwise you have no chance of ever
get this complex system really working (not to mention to adapt the
system for future changes).

So NHibernate requires some constructors or all properties virtual?
Never mind. Rules of thumb like persistence ignorance should guide
you, they are not strict laws and you won't be shot if you follow
common sense. :)

--
Until the next mail...,
Stefan.

Greg Young

unread,
Oct 7, 2008, 5:46:14 PM10/7/08
to nhu...@googlegroups.com
Funny in past conversations you determined that supporting constructor
mapping would require so much rewriting/rearchitecture that it wasn't
viable to look at ...

Now you ask me for a patch.

hmm.

Cheers,

Greg

Ayende Rahien

unread,
Oct 7, 2008, 6:05:37 PM10/7/08
to nhu...@googlegroups.com
I did? I don't recall that.

Ctor mapping isn't really different than the other forms of mapping that Nhibernate has.
It is different because you need to gather the data up front and then create the instance, but it is possible.
Start from Loader.GetRow and move from there.

It is not trivial, but it is not a major undertaking, I would say.

Fabio Maulo

unread,
Oct 7, 2008, 6:11:35 PM10/7/08
to nhu...@googlegroups.com


2008/10/7 MAMMON <die...@gmail.com>

but it DOES:
+ Force me to make all of my methods and properties virtual, for the
use of proxies

It is not NH. It is a requirement of Castle.DynamicProxy and in general a requirement of any kind of DynProxy.
Unluckily .NET don't give us a buildin system but, perhaps, we can do something using post#.
 
+ Force me to override Equals() and GetHashCode(), because of proxies

Not for sure. That is a best-practices if you are going to use ISet or if you are using composite-ID embedded in the class instead have a separate class for it.
 
+ Prevent me from putting logic in public property getters/setters,
because the proxies, upon hydrating objects, would incorrectly execute
that logic.

Not that is only your way to work. Who are using access trough fields don't have that problem (and NH have a lot of access strategy).
 

+ Create the "polymorphic databinding" problem with lists and
collections of objects, because of proxies.

No. NH give you the ability to write your own IUserCollectionType... the "problem" here is that nobody have time to write something to share with the community or nobody are really interested to have that feature.
 
--
Fabio Maulo

Fabio Maulo

unread,
Oct 7, 2008, 6:24:20 PM10/7/08
to nhu...@googlegroups.com
If you want I have the only one unsolvable intrusion
With NH you must have an ID as your POID even if your Entity don't need it

In the past I found 3 intrusions of NH in my entities but when I saw the NH core code I understand that the other 2 was only because I'm asking to NH to solve some other matters and for each I must pay something if I don't want to write a lot of code.

--
Fabio Maulo

P.S. well... "I don't want to write a lot of code"... I mean out side NH core.

Ayende Rahien

unread,
Oct 7, 2008, 6:30:30 PM10/7/08
to nhu...@googlegroups.com
On Wed, Oct 8, 2008 at 12:24 AM, Fabio Maulo <fabio...@gmail.com> wrote:
If you want I have the only one unsolvable intrusion
With NH you must have an ID as your POID even if your Entity don't need it

Can't you just not specify the ID in the mapping? That will make NH manage it intenrally. 

 
P.S. well... "I don't want to write a lot of code"... I mean out side NH core.
LOL 

Fabio Maulo

unread,
Oct 7, 2008, 6:50:22 PM10/7/08
to nhu...@googlegroups.com
2008/10/7 MAMMON <die...@gmail.com>

With a lot of Entity Framework buzz being generated recently, due to
it's v1 release with VS2008 SP1, the term Persistence Ignorance has
been climbing the Google ranks ladder.  Indeed, a Google search of the
term shows that of the top 5 results, 3 are about the Entity
Framework.  Since I work in an otherwise all Microsoft shop, I am very
interested in the EF, and the recent buzz has caused me to think more
about Persistence Ignorance.  Out of the box, EF doesn't have it, but
someone at MS has created a PI POCO adapter for EF v1.

Please don't compare NH with EF.
You can't compare 4 crazy dogs with a monster as Microsoft.
Give us the same funds, or a part of it, and then we can make some comparison.

BTW EF is the future because Microsoft (the word Microsoft don't need any other explication), and NH is the present.

2 weeks ago, for a new project, I have proposed LINQ2SQL in a company (yes, I have proposed LINQ2SQL) but that company said NO even if that project will work only with MSSQL. They choose NH.

I don't want to talk for Ayende but... when some big OSS developer say you "write your own" or "patch it" it is because the day have only 24hours and who write code for free need help to solve all issues.
Without the help of the community the OSS can't live forever.
--
Fabio Maulo

Ayende Rahien

unread,
Oct 7, 2008, 6:56:48 PM10/7/08
to nhu...@googlegroups.com
My point of view on that is quite simple, I am working on open source projects for many reasons.
Part is personal pleasure, part is to have good tools at my disposal. 
My interest in adding features that I don't need and don't care about is low. Developing software takes time, and unless I, personally, see a benefit out of it (which can be as nebulous as 'I find this interesting' or 'wouldn't it be cool'), I rarely take the trouble to do so.
When people make feature requests, they tend to in several categories, bug fixes or features that I think I would use I tend to value more than features that I don't see myself using and don't really give me much of a benefit. For those people, I suggest doing it themselves or paying to have it done. It is that simple.

MAMMON

unread,
Oct 7, 2008, 8:37:45 PM10/7/08
to nhusers
I didn't compare NH with EF. I simply mentioned that due to recent EF
buzz, and EF's LACK of Persistence Ignorance, the topic of PI had been
on my mind. The only phrase that could have been interpreted as a
comparison between the two was when I praised NHibernate, mentioning
how nice it was that I didn't have to inherit from some specific base
class in order to have persistence functionality.

Nathan Stott

unread,
Oct 7, 2008, 8:56:19 PM10/7/08
to nhu...@googlegroups.com
If EF is the future, then I don't want to see tomorrow.

Sidar Ok

unread,
Oct 7, 2008, 9:02:50 PM10/7/08
to nhu...@googlegroups.com
inline, having played with the POCO adapter for EF, my 2 cents would be do not use it, and not let any of your good friends do so. Seriously, PI is not that important to create 3 levels of mapping just to achieve it. (even the built in 2 makes me choke, but that's even another inline discussion)

Liviu U

unread,
Oct 8, 2008, 2:52:52 AM10/8/08
to nhu...@googlegroups.com
There is another way to go, when talking about Persistence Ignorance.

I define all my model entities as interfaces in a separate assembly.
I have a "code generator " that takes care of all the plumbing for me:
1) generates the classes as the storage wants them : NH virtual
methods, primary keys

Liviu U

unread,
Oct 8, 2008, 2:57:35 AM10/8/08
to nhu...@googlegroups.com
There is another way to go, when talking about Persistence Ignorance.

I define all my model entities as interfaces in a separate assembly.


I have a "code generator " specific for each storage that takes care


of all the plumbing for me:
1) generates the classes as the storage wants them : NH virtual

methods, primary keys,
2) NH mappings
3) registeres the implementation classes with the interfaces so
they are accessible from my IOC


Advantages:
the model is not poluted in any way: no attributes, no id
properties, no reference to any ORM
if i have to change something regarding to persistence i do that in
one place, but not in my "model"


Regarding rules and validations: i use my own rules engine that is
specified against interfaces and "weaved" at runtime.

Regarding : code it yourself advice, this is the biggest pain in the
**** with open source projects that do not have the guts to take
documentation to the level it will make it easy for other folks to
understand and help the project grow.

Ayende Rahien

unread,
Oct 8, 2008, 3:09:50 AM10/8/08
to nhu...@googlegroups.com
Liviu, 
We would be glad to accept all the help that you can provide with writing documentation.
Reply all
Reply to author
Forward
0 new messages