Circular Reference, NHibernate and WCF

This problem pops around the network for years, I've found no good solution yet. The topic is passing a List of Objects which have circular reference inside them populated by NHibernate (with or without lazy load - some sites sais it can't be done with lazy)

Here is the example:

[DataContract]
class Person
{
   [DataMemeber]
   string Name
   [DateMember]
   IList<Child> myChilds;  
}

[DataContract]
class Child
{
   [DataMemeber]
   string Name
   [DateMember]
   Person Father   
}

When I try to get all the Persons in my DB: The server code will be:

ICriteria crit = session.CreateCriteria(typeof(Person)));
IList<Base> queryResult = crit.List<Base>();

I get a good results on the SERVER SIDE- a List of all the person, and inside every person I get an List of all the sons (and inside each son - I get an object of Person which inside has an List of his sons ect....)

Now, Trying to Get this List over WCF faults the channel. (if I remove the Person object from the child - it works fine).

Solutions I've tried and did not solved this issue: adding IsReference=true to [DataContract] - didn't help. Moveing all the mapping to not.Lazyload() - didn't help.

Any Ideas how to solve this without rewriting WCF ?

Thanks, Dani

13.10.2009 15:07:27
3 ОТВЕТА

It looks like your problem is the size of the response. WCF has configuration for the size of the message to be sent. When you include the sub objects you are going over the limit.

0
13.10.2009 15:20:09
the default size of WCF is 512K. I have only 5 "Person" objects, and only 1 of them has a son. This might be a size issue - due to infinite loop of serialization, but the original structure, is no more than a few K's....
Dani 13.10.2009 16:02:44

IsReference is indeed the official answer here if you want to actually preserve the shape of the object graph. See http://msdn.microsoft.com/en-us/library/cc656708.aspx . Can you elaborate on what you mean when you say "it didn't help"? Where exactly did you put IsReference? On both client and server side? What errors did you observe?

If you don't care about ref preservation, there are various solution that involve breaking the infinite reference cycle. The simplest one is to remove DataMember attribute from "Father". Or something with a "shadow property":

public Person Father;
[DataMember] public string FatherName
{ get {return Father.Name;} set {/* ... */ }}   

It really strongly depends on your exact requirements...

0
14.10.2009 08:05:27
I've put the IsReference on the DataContract Attribute, In the linked article they say it should be on the problematic [DataMember] BUT... surprisingly - [DataMember] doesn't know about this flag. this code will not compile !! (which is very strange being the source of the example is MSDN...) Systme.RunTime.Serialization DataMemberAttribute does not contain definition for IsReference=true..... A Puzzle.
Dani 14.10.2009 08:19:55
Hmm, yes, didn't notice the topic was broken... Still: - Did you put IsReference on both Child and Person types? - What happened exactly when you tried IsReference? (Exceptions, etc.?)
Eugene Osovetsky 14.10.2009 16:02:49
Same Exception - as nothing changed. The exception is general, nothing specific. I've read an article suggesting moving to another serializer. I'm checking this option and I'll report back here. I've ask someone @ Microsoft about this article, still waiting for an answer.
Dani 14.10.2009 19:17:33
РЕШЕНИЕ

http://www.jameskovacs.com/blog/CommentView.aspx?guid=477b077c-e65e-4547-8289-4e1bc17b3de7

This Article solves the problem.

EDIT:

Link has apparently been dead for some time. Use the Wayback Machine to see the archived version of it here: http://web.archive.org/web/20070219214621/http://www.jameskovacs.com/blog/CommentView.aspx?guid=477b077c-e65e-4547-8289-4e1bc17b3de7

2
2.02.2012 20:28:36