tags:

views:

101

answers:

3

NHibernate requires not only settable properties of your domain to be virtual but also get-only properties and methods. Does anyone know what the reason for this is?

I cannot imagine a possible use.

+2  A: 

I'm not an NHibernate expert, but from reading Oren's blogs, and from what I've learned of NH, the basic pattern of use is to proxy the objects for the ORM. This means, among other things, that the only things you'll be able to map are going to be things that are made virtual, otherwise NH would have to use a different strategy to redefine the implementations under the hood.

Joseph
Well yes, but I obviously don't want to map method calls...
George Mauer
@George I think it has to do with what that method will need, and making sure that the object is loaded correctly. If it's not then it might need to go and get something. Again, I'm not entirely sure, but I do remember reading the elevator speech for the ORM was to use the proxy pattern to hook into your domain objects.
Joseph
+1  A: 

Because you may want to access your settable properties from there, and maybe in some fancy indirect or reflection way. So it's to be 100% sure that when your entity is used, it's initialized. Example:

public string GetSmth 
{
  get
  {
     // NHibernate will not know that you access this field.
     return _name;
  }
}
private string _name;
public virtual string Name { get { return _name; } set { _name = value; } }

Here's Ayende explaing this in relation to Entity Framework: http://ayende.com/Blog/archive/2009/05/29/why-defer-loading-in-entity-framework-isnrsquot-going-to-work.aspx

AddProduct is a non virtual method call, so it cannot be intercepted. Accessing the _products field also cannot be intercepted.

The only reason I see why one would want method execution without messing with NH proxy (i.e. loading data) is when you have method that do not access your class' data. But in this case, if this method does not use your class' data, what does it belong to that class at all?

queen3
+5  A: 

The reason is lazy loading. In order to make lazy loading possible, a proxy class is created. It must intercept every call from "outside" in order to load your entity before actual method/property is executed. If some methods/properties were not virtual it would be impossible to intercept these calls and entity wouldn't be loaded.

maciejkow
It's still OK if these non-intercepted properties use "virtual"/"intercepted" ones - because NHibernate will detect it at the time of invocation. Problem appear if you use camelcase-underscore fields and so on.
queen3
I understand how it works, but I could just be leaving something virtual because I don't want it intercepted. It seems like a very odd design decision to force you to allow NHibernate to get access to it 0 or is there some other technical reason that I'm missing?
George Mauer
If you leave any method unintercepted and then try to access any private field, method from it - your entity will NOT be initialized. When everything has to be virtual it is impossible to make that mistake - this is definitely one of the reasons for this restriction.
maciejkow
I see good reasons behind NHibernate decision, but I don't see why one wouldn't want a method to be intercepted... is it kind of harrasment or something? After all, JIT intercepts your methods anyway.
queen3
Any particular reason you don't want your method to be intercepted?
maciejkow
@George Mauer: In order for lazy loading to work at all, all of the properties need to be virtual. In fact, read-only properties are the ones *most* in need of being virtual, as they are typically the ones that are loaded by some other method (constructor, etc.).If the read-only properties weren't virtual, you couldn't have lazy loading, as the constructor args would have to be loaded from the DB prior to instantiation.
Harper Shelby
Ahh ok, I get it
George Mauer