Stop lazy loading or skip loading a property in NHibernate? Proxy cannot be serialized through WCF
Consider I have a parent, child relationship class and mapping. I am using NHibernate to read the object from the database, and intended to use WCF to send the object across the wire.
Goal
- For reading the parent object, I want to selectively, at different execution path, decide when I would want to load the child object. Because I don't want to read more than what I needed.
- Those partially loaded object must be able to sent through WCF. When I mean I don't load it, neither side will access such property.
Problem
- When such partially loaded object is being sent through WCF, as those property is marked as
[DataContract]
, it cannot be serialized as the property is lazy load proxy instead of real known type.
What I want to archive, or solution that I can think of
lazy=false
orlazy=true
doesn't work. Former will eagerly fetch all the relationships, latter will create a proxy. But I want nothing instead - anull
would be the best.- I don't need lazy load. I hope to get a
null
for those references that I don't want to fetch. A null, but not just a proxy. This will makes WCF happy, and waste less time to have a lazy-load proxy constructed. Like could I have a null proxy factory? -OR- - Or making WCF ignoring those property that's a proxy instead of real. I tried the IDataContractSurrogate solution, but only parent is passed to
GetObjectToSerialize
, I never observe an proxy being passed throughGetObjectToSerialize
, leaving no chance to un-proxy it.
Edit
After reading the comments, more surfing on the Internet...
It seems to me that DTO would shift major part of the computation to the server side. But for the project I am working on, 50% of time the client is "smarter" than the server and the server is more like a data store with validation and verification. Though I agree the server is not exactly dumb - I have to decide when to fetch the extra references already, and DTO will make this very explicit.
Maybe I should just take the pain. I didn't know http://automapper.codeplex.com/ befor开发者_JAVA技巧e, this motivates me a little more to take the pain.
On the other hand, I found http://trentacular.com/2009/08/how-to-use-nhibernate-lazy-initializing-proxies-with-web-services-or-wcf/, which seems to be working with IDataContractSurrogate.GetObjectToSerialize
.
Was getting the same issue with WCF-Silverlight transferring of DTO/Entities. I use following code which works fine:
Fluent NHibernate:
References(c => c.DataSource)
.Column("DataSourceId")
.Cascade.None()
.Not.LazyLoad();
HasManyToMany(c => c.Categories)
.Table("Categories")
.ParentKeyColumn("ItemId")
.ChildKeyColumn("CategoryId")
.Not.LazyLoad()
.Cascade.None()
.Inverse();
XML:
<many-to-one name="DataSource" column="DataSourceId" lazy="false" cascade="none" />
Hope this'll work for you!
I have run into similar issues with performance, what I did instead was preload the information I want by using an explicit call to the DB using a DetachedCriteria.
So similar to what you are doing I would probably do something like this.
public DetachedCriteria BuildMyCriteria()
{
var criteria = DetachedCriteria.For<ParentClass>();
criteria.CreateCriteria("this.ChildClass", "Child Class").SetFetchMode("this.ChildClass", FetchMode.Eager);
criteria.Add(Restrictions.IsNotNull("ChildClass.Property");
return criteria;
}
Then from my facade, I would get those entities with the properties that do not have null attributes on the child property
var myClasses = _repository.ExecuteDetachedCriteria<ParentClass>(BuildMyCriteria);
Then I would have all ParentClass entities that have a null property.
So instead of taking a hit by constantly asking the DB for info, I store it in memory so it is ready for me to use.
This is just an alternative solution to DTOs, good luck :)
精彩评论