Hi,
I am involved in development of application having a bit unusual setup
regarding use of lazy load proxies.
The application is client/server implemented in ClickOnce technology (the
client) and .NET remoting (communication between client and server).
Entity classes are rather complex (several levels of relations,
many-to-many collections, inheritance etc.) and are use both on server as
well as at client side.
In the old days (NH 2.0) it was a problem to use dynamic proxies in
nhibernate because ClickOnce client wasn't able to deserialize entities
having collections of such lazy proxies (due to security issues).
The we invented was to implement own IProxyFactory and return manually
constructed proxies. So, for each entity EntityX there is also a
corresponding EnityXLazyLoadProxy which is includes dummy implementation:
[Serializable]
public class EnityXLazyLoadProxy : EntityX , INHibernateProxy
{
public ILazyInitializer HibernateLazyInitializer
{
get;
set;
}
}
The solution worked fine (with a limitation that lazy entities can't be
initialized on demand, but that wasn't a concern).
Recently I investigated content of serialized objects and found out that
there is some "garbage" included which shouldn't be there, because entity
was transmitted as LazyLoadProxy only
(by garbage I mean e.g. real values of properties, for example very long
strings which I would like to avoid transmitting).
It turned out to be caused by the fact that HibernateLazyInitializer field
was also serialized, with all its fields (e.g. Target).
So, I changed it to not serialize that field:
[NonSerialized]
private ILazyInitializer _HibernateLazyInitializer;
public ILazyInitializer HibernateLazyInitializer
{
get { return _HibernateLazyInitializer; }
set { _HibernateLazyInitializer = value; }
}
This works fine (no more "garbage" in serialized stream containing
LazyLoadProxy-ies).
But it causes another problem: sometimes i need to send a object from
client to server containing LazyLoadProxy-ies (previously received form
server, of course).
Such entity is the merged to the session server side. And this fails:
MESSAGE:
System.NullReferenceException : Object reference not set to an instance of an
object.
+++++++++++++++++++
STACK TRACE:
Server stack trace:
at NHibernate.Impl.SessionImpl.GetContextEntityIdentifier(Object obj)
at NHibernate.Type.EntityType.Replace(Object original, Object target,
ISessionImplementor session, Object owner, IDictionary copyCache)
at NHibernate.Type.TypeHelper.Replace(Object[] original, Object[] target,
IType[] types, ISessionImplementor session, Object owner, IDictionary
copiedAlready)
at
NHibernate.Event.Default.DefaultMergeEventListener.CopyValues(IEntityPersister
persister, Object entity, Object target, ISessionImplementor source,
IDictionary copyCache)
at
NHibernate.Event.Default.DefaultMergeEventListener.EntityIsDetached(MergeEvent
event, IDictionary copyCache)
at NHibernate.Event.Default.DefaultMergeEventListener.OnMerge(MergeEvent event)
at NHibernate.Impl.SessionImpl.FireMerge(MergeEvent event)
at NHibernate.Impl.SessionImpl.Merge(String entityName, Object obj)
at NHibernate.Impl.SessionImpl.Merge(Object obj)
at NHibernate.Impl.SessionImpl.Merge[T](T entity)
I've checked source of GetContextEntityIdentifier(...) and it assume that
if object is a proxy, then HibernateLazyInitializer property should be
there.
So, I'm looking for any hint how to guarantee the HibernateLazyInitializer
is initialized for objects deserialized at server side. I suppose
session.Merge is not the only method that might fail in this case (or maybe
I'm wrong?)
Or maybe any hint how to prevent transmitting "garbage" not marking
HibernateLazyInitializer's field as [NonSerialized]?
greetings,
Bartek
--
You received this message because you are subscribed to the Google Groups
"nhusers" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/nhusers.
For more options, visit https://groups.google.com/d/optout.