问题
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.
回答1:
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.
回答2:
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.).
回答3:
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
回答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));
}
来源:https://stackoverflow.com/questions/9843310/are-there-occasions-when-nhibernate-wont-return-a-proxy-object