As per the title, I have an object which has a ReferencesAny association, but it's possible that the referenced object may have been deleted. If this has occurred, currently the missing object is initialized with a proxy which then throws ObjectNotFound if accessed. I want to be able to have this return null instead, in a similar fashion to setting not-found to "ignore" on other properties. I understand the differences between using Session.Get and Session.Load but this is occurring as a result of a LINQ query.
So, my question is, how can I specify that null should be returned for missing objects for an "any" association?
I am using xml configuration, but I guess that my hint could help you anyway... NHibernate provides for those incomplete mappings an attribute not-found which is by default set to "exception". In this example is reference many-to-one mapping, but it could be used even for one-to-many
<many-to-one name="MyReferencedObject" not-found="exception" />
but it can be changed to ignore
<many-to-one name="MyReferencedObject" not-found="ignore" />
In that case the result will be NULL. (But be careful, NHibernate will always execute a SQL select statement, because such a "NULL" value won't be cached)
EDIT: based on the comment below, I have to say, that my suggestion is not working for <any> mapping. Sorry for that, I should read more carefully... But, please, let me provide you with suggestion, how to fix it.
We can introduce event listener. More can be found here http://nhibernate.info/doc/nh/en/index.html#objectstate-events
Solution in a nutshell:
Introduce the event listener
public class PostLoadListener
: NHibernate.Event.Default.DefaultPostLoadEventListener
{ ... }
and inject it into the "session-factory" configuration.
<event type="post-load">
<listener class="MyLib.PostLoadListener, MyLib"/>
</event>
The trick would be inside of the overriden method OnPostLoad
public override void OnPostLoad(PostLoadEvent @event)
{
base.OnPostLoad(@event);
// the entity with <any> mapping
ConvertToNull(@event.Entity as MyAuditEntity);
}
protected virtual void ConvertToNull(MyAuditEntity item)
{
if (item == null)
{
return;
}
try
{
// access some property to check that reference is not a PROXY
var id = item.AnyEntity.ID;
}
catch
{
// replace proxy with null
item.AnyEntity = null;
}
}
Of course, this is not the answer like not-found="ignore". But this workaround will do that job.