0

I went back to the "drawing board" on a post I had written earlier concerning a StackOverflowException while trying to serialize an EF STE object graph... After failing to successfully adjust the stack size in IIS7, as described here, I decided to go down the path of looking into the the root cause...

I believe it has to do with the way the EF model has been designed.

Simplified, I have a Parent entity and a Child entity. The Child entity has two navigation properties back to Parent, e.g. Child.Parent and Child.ParentUsed. Naturally, the parent has two Child collections.

After looking closer at the data that causes the StackOverflow exception, I noticed there are several cycles in this object graph. I can't prove it, but I'm fairly positive that the cycles are causing this StackOverflow exception.

If I remove the data this table in the database, the problem goes away, but I won't be able to remove the records on the customer's machine. Bad design or not, I have to work around this at the EF level somehow.

What are my options to rework this? If my Child object didn't have navigation properties back to the parent, but instead had two int Fks, I wonder if there would be cycles that caused the serialization to choke? Is there a way to change navigation properties to Fks on one entity?

Thanks!

Update:

Removing both of the child's navigation properties back to the parent resolves this issue. I don't think it's necessarily a cycles issue, but perhaps the stack is exhausted trying to check for references and determine cycles.

I don't necessarily want to remove the nav properties. They are useful on the client. Is there a better way to fix this? Custom serialization?

Community
  • 1
  • 1
John Russell
  • 2,177
  • 4
  • 26
  • 47
  • What do you mean by cycles? STEs are marked with `DataContract(IsReference=true)` to detect cycles so they serialize each entity in object graph only once (when using `DataContractSerializer`). – Ladislav Mrnka Jun 19 '12 at 08:02
  • Yes, I thought the same thing. All my entity classes are marked with DataContract(IsReference=true). – John Russell Jun 19 '12 at 12:08
  • How did you find that issue is caused by cycles? Are you sure that your STEs don't reference any custom class not marked with attribute? – Ladislav Mrnka Jun 19 '12 at 13:05
  • Good call. I don't think it's a cycle issue at all. I was able to prove this by retrieving the EF object graph from the database in question, serializing the graph using the DataContractSerializer. I specified a Surrogate to the serializer's constructor and kept track of the Ids of each serialized object. No Id was performed twice. Perhaps it's the object graph is too deep for the serializer to handle it within the 256kb stack limit that IIS imposes. Any ideas on how this can be overcome? I could possible split the entity serialization out, but then I'd have to re-assemble on the client. – John Russell Jun 19 '12 at 16:05
  • I have never had this problem so I can't help. I was just curious how could STEs produce cycles. How many objects do you have in serialized graph? – Ladislav Mrnka Jun 19 '12 at 20:41
  • About 4000 objects total. 6-7 levels deep. – John Russell Jun 19 '12 at 20:48

1 Answers1

1

I've had a simillar problem when I was testing performance of EF with WCF. I was getting a StackOverflow when the result set of the query was above 3000 results.

If you eliminate just one of the navigational properties the StackOverflow will desapear. I will try to explain where the cycle happens, but you can all also try to serialize your graph to a file with the DataContractSeriazer and you will realize whats wrong the moment you see the generated XML.

Each object is serialized only once, however the serialization is depth first. Tacking your scenario as an example:

1 - serialiaze parent1

2 - serialize first element of ChildList1

3 - now we are serializing object Child1 that has relation to the parent1 (already serialized so a Ref is used). So serialize ParentUsed (a different object, parent2, with more relations to other childs) - Go step 1 for parent2

If the list of parents loaded and the complexity of the relations (between records) is big enough, the serializer will try to serialize all of the graph as "childs" (recursively) of the first element. Removing one of the navigational property back to parent will eliminate the cycle has the reamaining navigational property will always referentiant a parent that was already serialized.

If you only use Navigational properties for binding to the UI you can use more than one BindingSource (I'me used to WinForms) and the FK to make relations and achieve the same result as with navigational properties (although with more work involved).

Hope this helps,

Nuno Pereira

nflash
  • 430
  • 3
  • 16