BeginEdit causing out of memory

Nov 24, 2011 at 1:13 AM
Edited Nov 24, 2011 at 1:15 AM

Hey Tony,

Been working through your examples, nice toolkit.  I finally got comfortable to try my own example in Windows Phone 7.

I've run into an issue while doing an update on a record.  The basic scenario is a list view / detail view.

When a record is selected from the listview, I navigate to the detail view, after setting the datacontext properly, I set the viewmodel to BeginEdit in the page loaded event.

At this point, it hangs and after a long while, I get an OutOfMemoryException.  Can you tell me if there are any special requirements for the model to use the BeginEdit / EndEdit?

Stack trace is attached:

   at System.Xml.XmlWellFormedWriter.AddNamespace(String prefix, String ns, NamespaceKind kind)
   at System.Xml.XmlWellFormedWriter.PushNamespaceImplicit(String prefix, String ns)
   at System.Xml.XmlWellFormedWriter.WriteStartElement(String prefix, String localName, String ns)
   at System.Xml.XmlDictionaryWriter.XmlWrappedWriter.WriteStartElement(String prefix, String localName, String namespaceUri)
   at System.Xml.XmlDictionaryWriter.WriteStartElement(String prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri)
   at System.Runtime.Serialization.XmlWriterDelegator.WriteStartElementPrimitive(XmlDictionaryString localName, XmlDictionaryString namespaceUri)
   at System.Runtime.Serialization.XmlWriterDelegator.WriteInt(Int32 value, XmlDictionaryString name, XmlDictionaryString ns)
   at System.Reflection.RuntimeMethodInfo.InternalInvoke(RuntimeMethodInfo rtmi, Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture, Boolean isBinderDefault, Assembly caller, Boolean verifyAccess, StackCrawlMark& stackMark)
   at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, StackCrawlMark& stackMark)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at System.Runtime.Serialization.XmlFormatWriter.TryWritePrimitive(Type type, Object value, MemberInfo memberInfo, Int32 arrayItemIndex, XmlDictionaryString ns, XmlDictionaryString name, Int32 nameIndex, XmlDictionaryString[] memberNames, Object& objectLocal, DataContract contract, XmlObjectSerializerWriteContext context, XmlWriterDelegator xmlWriter)
   at System.Runtime.Serialization.XmlFormatWriter.WriteMember(SerializingObject serObj, Int32 memberIndex, ClassDataContract derivedMostClassContract)
   at System.Runtime.Serialization.XmlFormatWriter.WriteClass(CallStackElement`1 callStackElement)
   at System.Runtime.Serialization.XmlFormatWriter.Serialize(XmlObjectSerializerWriteContext context)
   at System.Runtime.Serialization.XmlFormatWriter.InitializeCallStack(XmlWriterDelegator xmlWriterDel, Object obj, XmlObjectSerializerWriteContext writeContext, DataContract contract)
   at System.Runtime.Serialization.ClassDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context)
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
   at System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph)
   at System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph)
   at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph)
   at System.Runtime.Serialization.XmlObjectSerializer.WriteObject(XmlDictionaryWriter writer, Object graph)
   at System.Runtime.Serialization.XmlObjectSerializer.WriteObject(Stream stream, Object graph)
   at SimpleMvvmToolkit.ModelExtensions.Extensions.Clone[T](Account obj)
   at SimpleMvvmToolkit.ViewModelDetailBase`2.BeginEdit()
   at Test.Views.AccountUpdateView.PhoneApplicationPage_Loaded(Object sender, RoutedEventArgs e)
   at MS.Internal.CoreInvokeHandler.InvokeEventHandler(Int32 typeIndex, Delegate handlerDelegate, Object sender, Object args)
   at MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, Int32 actualArgsTypeIndex, String eventName)

Nov 24, 2011 at 3:41 AM

I suspect that the maybe the Clone method using the DataContractSerializer is not able to make a deep copy of the linq entity since I have EntitySets.

Coordinator
Nov 27, 2011 at 10:14 PM

Most likely you have objects with circular references. However, you should not use the BeginEdit method when using RIA Services, which has its own implementation of IEditableObject.  Just go ahead and edit the entities without using BeginEdit or EndEdit.  RIA should take care of tracking the changes.

Cheers,

Tony

Nov 27, 2011 at 10:58 PM

Hi Tony,

Thanks for replying.  I am not using RIA and I don't think I have circular references unless the EntityRef / EntitySet effect this.

Anyways, I created code to keep track of it.

Coordinator
Nov 28, 2011 at 12:15 AM
Clone uses the DataContract serializer. Do your entities have DataContract with IsReference=true?
Nov 28, 2011 at 2:15 AM

Hi Tony,

Yeah, I forgot to add the DataContract, thanks.  I couldn't add the isreference = true because the modelbase has isreference = false and derived types must have the isreference type.

Coordinator
Nov 28, 2011 at 11:18 AM

Ah, that would be a problem.  Can you try coping the code for ModelBase into your project and setting IsReference = true on the [DataContract] attribute, then see what happens?  This would let us know if there is a cycle problem.  If not, I would want to know more about your object graph and its size.

Nov 29, 2011 at 5:51 AM

Hey Tony,

I will try this when I get a chance.  I'm just playing around with the toolkit.  Thanks.

Sep 27, 2012 at 3:49 AM
Edited Sep 27, 2012 at 3:51 AM

Hi Tony,

I have run into similar problem during BeginEdit. It says that I might have cycle reference. I have decorated my class with

[DataContract(IsReference = true)]

and same for ModelBase as well using source code (Build 15294)

I still get an error during BeginEdit. What is the best possible way to solve this.

Thanking you in advance.

Coordinator
Sep 27, 2012 at 1:14 PM

Can you reproduce the problem in a small project and send it to me?

Thanks,

Tony
tony@tonysneed.com 

Sep 28, 2012 at 2:07 AM

Hi Tony,

I had a cycle reference in the model that I was trying to edit. I had a reference to a class in a model, which in turn had a reference to a collection and to which the model I was about to edit was a item in that collection. Hence the error. (I guess). Will try and implement some other way. Please let me know if there is any better way to edit in such scenario.

Cheers and thanks for answering promptly.

Coordinator
Oct 19, 2012 at 10:32 PM

This issue is now fixed in v3.1.0.0 of the toolkit, which uses a logical XOR operator to avoid hash code collisions.