Reputation: 2286
I have 2 objects in my domain A, and B
Object A has a property of B Object B has a property of list
when I do a hit on my db, of B, it returns a list of As, but each A has a B, which in turn has a list of As. over and over and over.
clearly a lazy loading issue. Lazy loading is on, but my problem is that this is a WCF service, do i need to convert all my domain objects into dto objects to send down the wire and when i do it does the following - pseudocode
ADTO adto Transform(ADomain a)
{
adto.name = a.name;
adto.surname = a.surname;
adto.B = Transform(a.B);
}
BDTO bdto Transform(BDomain b)
{
bdto.bob = b.bob;
foreach (A a in b.As)
{
bdto.bs.add(Transform(a));
}
}
so how can i make my fetch of the collection only go one layer deep.
B's mapping:
HasMany(x => x.As)
.Cascade.AllDeleteOrphan()
.Fetch.Select()
.Inverse().KeyColumn("AId");
A's mapping:
References(x => x.B).Column("AId");
Upvotes: 3
Views: 2226
Reputation: 123861
Well, to pass circular reference over WCF you should adjust the Parent DTO (B) with IsReference
parameter DataContractAttribute.IsReference Property (or here The Problem of Circular References).
Use the IsReference property to instruct the DataContractSerializer to insert XML constructs that preserve object reference information.
[DataContract(Namespace = "http://domain.../", IsReference=true)]
public class BDTO ...
To give you answer:
...so how can i make my fetch of the collection only go one layer deep.
NHibernate won't have any issue with circular references. And even more, you can easily get all the data while executing 2 SQL queries only. Adjust the mapping:
HasMany(x => x.As)
.Cascade.AllDeleteOrphan()
.BatchSize(25)
//.Not.LazyLoad()
.Inverse()
.KeyColumn("AId");
NOTE: Not.LazyLoad make sense only if the A object is almost always needed to get B working. When "lazy" mode is used, you have to keep the session opened during the whole WCF service processing
The BatchSize setting will optimize loading lists of B objects. Read more here: http://ayende.com/blog/3943/nhibernate-mapping-set
NHibernate session will execute two queries 1) Select B
and 2) Select A for all B
and materialize the results into complete A and B instances, with both-ways references fully populated. The NHibernate session will serve you fully loaded instances. Even calls Get<A>(id)
and Get<B>(id)
will retrieve the objects from session
Next steps are up to you, you can use DTO objects, mapping tools to convert them...
Upvotes: 1