Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NHibernate Futures returns Proxy sometimes, Entity others

I have a database fetch that handles a full object graph using multiple future queries. It looks something like this (class names have been changed to protect the innocent):

Foo foo;
var fooFuture = Session.QueryOver<Foo>()
                       .Where(f => f.Id == id)
                       .Future();

// load up the Blah collection for the Foo
Session.QueryOver<Foo>()
       .Fetch(f => f.Blahs).Eager
       .Where(f => f.Id == id)
       .Future();

// do a separate query for the BlahOptions -- this is needed
// because if we did a Join and Join off of Foo, we'd get duplicate Blah
// results and that's not good
Session.QueryOver<Blah>()
       .Fetch(b => b.Options).Eager
       .Where(b => b.Foo.Id == id)
       .Future();

// load up the Attributes for the Foo
Session.QueryOver<Foo>()
       .Fetch(f => f.Attributes).Eager
       .Where(f => f.Id == id)
       .Future();

foo = fooFuture.SingleOrDefault();

NOTE: I can implement this in NHibernate LINQ, but the behavior remains the same.

The weirdness: foo will sometimes be of type FooNamespace.Foo (the correct, concrete type) and other times it will be Castle.Proxies.FooProxy.

Whether I get the real type or a proxied type seems to depend on whether or not NHibernate has been used previously in the session. When this query occurs after other NHibernate queries, it returns a FooProxy. If it's the first use of the session, it returns a Foo.

Why does this happen? How can I prevent it from happening? I'm purposefully fetching the entire object graph of Foo to make sure there are no proxies. And graph itself doesn't contain any proxies, it's just the root Foo reference. The fact that the returned type depends on what NHibernate has done before seems to be the key (and really weird).

A couple closing notes:

  • NHibernateUtil.IsInitialized returns true when fed a FooProxy, so I can't assure it's not a proxy that way
  • I'm proxy-adverse because the graph will be serialized for caching purposes and deserialization croaks when working with FooProxy

Any insight is greatly appreciated!

like image 560
kdawg Avatar asked Dec 02 '25 06:12

kdawg


1 Answers

The reason why this would generally happen is because a Foo is loaded elsewhere in the session prior to this point and you are getting the proxy created on that previous query.

I have had some success with the following

var fooProxy = foo as INHibernateProxy;
if(fooProxy != null) {
   var context= Session.GetSessionImplementation().PersistenceContext;
   foo = context.Unproxy(fooProxy);
}

Though, In most cases the process of serialization seems to convert the Proxy to the correct type.

like image 85
sanbornc Avatar answered Dec 03 '25 18:12

sanbornc



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!