The reality is more complex. When you load an object using session.Load or you access a lazy resource, NHibernate returns a proxy object. This proxy object will be moistened (data will be downloaded from the database) the first time you access any of its properties. To achieve this, NHibernate generates a proxy class that extends the entity class and overrides all getters and seters properties. This works great when inheritance is not used, since you will not be able to distinguish between a proxy server and an entity class (base proxy class), for example. a simple proxy is MyEntity test will always work.
Now imagine that we have a Person object:
class Person {
And we also have a hierarchy of Animal classes:
public abstract class Animal { ... } public class Cat { ... } public class Dog { ... }
Now suppose the Pet property is loaded with laziness, when you request NHibernate for a personal pet, you will get a proxy object:
var pet = somePerson.Pet;
But since Pet is a lazy loaded property, NH will not know if it will be a Cat or Dog instance, so he will do his best and create a proxy server that extends Animal . The proxy will run a test for pet is Animal , but will not run tests for pet is Cat or pet is Dog .
Now suppose you get access to some property of the Pet object, forcing NH to load data from the database. Now NH will know that your pet, for example, is a Cat , but the proxy server has already been generated and cannot be changed. This will force NHibernate to issue a warning that the original proxy for Pet , which extends the Animal type, will narrow to introduce Cat . This means that now the proxy object for animals with pet.Id , which you create using session.Load<Animal>(pet.Id) , will expand Cat from now on. This also means that since Cat now stored as part of the session, if we load the second person who shares the cat with the first, NH will use the already available Cat proxy instance to populate the lazy-load property.
One of the consequences will be that the reference to the Pet object will be different from the link received by session.Load<Animal>(pet.Id) (in the object.ReferencesEqual sense).
// example - say parent and child share *the same* pet var pet = child.Pet; // NH will return proxy that extends Animal pet.DoStuff(); // NH loads data from DB var parent = child.Parent; // lazy-loaded property var pet2 = parent.Pet; // NH will return proxy that extends Cat Assert.NotSame(pet, pet2);
Now that can harm you:
Therefore, the moral is to avoid as much inheritance as possible in your domain model.