2

I'm learning Fluent NHibernate (and by extension, NHibernate generally). I'm using auto-mapping with some overrides, but I don't think that is important for the question (of course, if I'm wrong here I'll gladly update the question).

Given an ISession (and a few more assumed variables) I can return entities by their ID:

using (var session = SessionFactory.OpenSession())
{
    var user = session.Get<User>(userId);
}

My limited understanding was that NHibernate creates a proxy around the User mapped entity, yet when I test it (based on this):

Assert.That(user is INHibernateProxy, "Not a proxy.");

It appears as though my instance is not a proxy.

Are there occasions where proxies are not used? I'm hoping for the "missing piece" and praying this isn't the Friday afternoon brain-fail.

Community
  • 1
  • 1
Adam Houldsworth
  • 63,413
  • 11
  • 150
  • 187

4 Answers4

4

As NOtherDev stated, proxies are for lazy-loading. But even Session.Get sometime returns a proxy. This caught me off guard several times. If you use lazy loading for any column in the table by specifying lazy="true" like this:

<property name="Description" type="StringClob" not-null="false" lazy="true"/>

Session.Get will always return proxies for this type, and there is no way to unproxy the object. In fact, the proxy is the real object.

By the way, disabling lazy-loading is really, really a bad idea. You can read more about that here: NHibernate is lazy, just live with it

Doan Van Tuan
  • 525
  • 3
  • 11
  • What if I never ever want to use a proxy object? How can I ensure my objects are unproxied? – Shiv Dec 07 '21 at 03:13
4

Some questions are never too old ;) In real live, you usally get proxies by access "parent" of inverse relationship or by loading an object by Load(). But if the object has already been loaded in the cache before, you will get the type of the first access. So Load/Get might both return proxy or real instance.

        // if object has been loaded, load will return real instance
        using (var session = CreateSession())
        {
            postByGet = session.Get<Post>(post1Id);
            postByLoad = session.Load<Post>(post1Id);

            Assert.IsFalse(postByGet is INHibernateProxy);
            Assert.IsFalse(postByLoad is INHibernateProxy);
            Assert.IsTrue(object.ReferenceEquals(postByGet, postByLoad));
        }

        // if proxy has been loaded, get will return filled proxy
        using (var session = CreateSession())
        {
            postByLoad = session.Load<Post>(post1Id);
            postByGet = session.Get<Post>(post1Id);

            Assert.IsTrue(postByGet is INHibernateProxy);
            Assert.IsTrue(postByLoad is INHibernateProxy);
            Assert.IsTrue(object.ReferenceEquals(postByGet, postByLoad));
        }
Fried
  • 1,323
  • 12
  • 21
3

Generally proxies are for lazy loading. Whenever you're fetching entitles by Get etc., you're not getting proxies, but the real objects. NHibernate don't use proxies when not necessary.

But if user has an Address, user.Address is INHibernateProxy will be true (unless lazy loading is turned off for this relationship).

For more info about how and when NHibernate handles proxies, see this article.

NOtherDev
  • 9,542
  • 2
  • 36
  • 47
3

ISession.Get always return either null or a real object. ISession.Load OTOH can return a proxy (or throw an exception), but proxying is a whole other story: your persistent classes should satisfy some preconditions (virtual properties, non-sealed, etc.).

Anton Gogolev
  • 113,561
  • 39
  • 200
  • 288
  • My understanding, which I think is flawed, was that proxies were always around. If I disable lazy loading, can I avoid proxies entirely? – Adam Houldsworth Mar 23 '12 at 17:05