In WCF, when using NetDataContractSerializer to enable .NET Remoting, DataContract objects are still serialized. Only ServiceContract objects are marshaled ByRef. The same setup is possible in native .NET Remoting, as well. It seems more likely to happen in WCF, though. Based on my experience, Remoting is usually all MarshalByRef or all Serialized - but that's just my experience. Either way, if you are serializing your object model, you need to be careful.
If you have a Parent<->Child bidirectional relationship in your DataContract objects, when you send the DataContract objects across WCF, they will be serialized/deserialized and the resulting hierarchy of objects will be: Parent->Child->CopyOfParent. This causes problems when using NHibernate to auto save/load your object tree.
For example, this object hierarchy:
Parent |--Child | |--Parent (reference to actual Parent)
Will end up looking like this, after being serialized / deserialized:
Parent |--Child | |--CopyOfParent (new object, independent of actual Parent)
To fix this, you'll have to manually re-build your references, after the objects are deserialized:
foreach(Child child in parent.Children)
{
child.Parent = parent;
}
If you don't rebuild the hierarchy references like this, NHibernate will not save or update your child objects correctly. You will either get "Transient Instance" exceptions or you will end up with orphaned children records because they will not have their parent id set correctly.
Here's an example of what one of my data access methods looks like, in an app that remotes the data access layers via WCF (and hides most of the NHibernate code in a base class):
public void Save(FooBar fooBar)
try
foreach(Widget widget in fooBar.Widgets)
widget.FooBar = fooBar;
OpenSession();
BeginTransaction();
Session.SaveOrUpdate(fooBar);
CommitTransaction();
catch
RollbackTransaction();
throw;
finally
CloseSession();
Although I haven't run into this situation yet, I am assuming that the same problem will occur if you have multiple parents pointing to the same child. For example, if you have:
Parent |--Child1 | |--GrandChild1 (same reference as Child2's GrandChild) |--Child2 | |--GrandChild1 (same reference as Child1's GrandChild)
When you send this structure across WCF as a set of DataContract objects, I imagine that you will end up with this:
Parent |--Child1 | |--GrandChild1 (duplicate of Child2's GrandChild) |--Child2 | |--CopyOfGrandChild1 (duplicate of Child1's GrandChild)
If your intention is to have Child1 and Child2 reference the same record in the database, you will need to reconstruct the Child1 and Child2 references to GrandChild1, ensuring that both point to the same object. I can see the basic code as traversing the children and comparing each of the gradchildren's values, then picking one winner between the same values and resetting the references on the rest of them. Unfortunately, I think the solution for this scenario would likely be unique to each situation, due to the complexity of picking the correct reference.
Has anyone run into this situation? If so, how did you solve it?
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.