LinqObservableCollection in Silverlight 4

LinqObservableCollection in Silverlight 4

Old forum URL: forums.lhotka.net/forums/t/9467.aspx


Smith866 posted on Thursday, September 02, 2010

I am having a problem with the LinqObservableCollection in CSLA 4 and Silverlight 4.

I have the following scenario:  I have a root object that contains a list of child objects.  In some situations, I want a filtered list of those child objects.  In order to achieve this, I added a property of type LinqObservableCollection<Child> to my root object.  In the getter, I perform a linq query on the list to give me the records that I want.  When I do the fetch, everything works fine.  I see my filtered list.

The problem is when I add items to the underlying list.  I add the items to the actual child list, not the LinqObservableCollection.  When I call save from my root object, I get the following exception:

System.Runtime.Serialization.InvalidDataContractException occurred

  Message=Type 'Csla.LinqObservableCollection`1[Business.RmAdmin]' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. Alternatively, you can ensure that the type is public and has a parameterless constructor - all public members of the type will then be serialized, and no attributes will be required.

  StackTrace:

       at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.ThrowInvalidDataContractException(String message, Type type)

       at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.CreateDataContract(Int32 id, RuntimeTypeHandle typeHandle, Type type)

       at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.GetDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type)

       at System.Runtime.Serialization.DataContract.GetDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type)

       at System.Runtime.Serialization.DataContract.GetDataContract(RuntimeTypeHandle typeHandle, Type type, SerializationMode mode)

       at System.Runtime.Serialization.XmlObjectSerializerContext.GetDataContract(RuntimeTypeHandle typeHandle, Type type)

       at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithXsiType(XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle objectTypeHandle, Type objectType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, Type declaredType)

       at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)

       at WriteSerializationInfo.FieldDataToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , ClassDataContract )

       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.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)

       at WriteKeyValueOfstringSerializationInfo.FieldDataOzoZvLrmToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , ClassDataContract )

       at System.Runtime.Serialization.ClassDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context)

       at WriteArrayOfKeyValueOfstringSerializationInfo.FieldDataOzoZvLrmToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , CollectionDataContract )

       at System.Runtime.Serialization.CollectionDataContract.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.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)

       at WriteSerializationInfoToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , ClassDataContract )

       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.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)

       at WriteArrayOfSerializationInfoToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , CollectionDataContract )

       at System.Runtime.Serialization.CollectionDataContract.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.DataContractSerializer.WriteObject(XmlWriter writer, Object graph)

       at Csla.Serialization.Mobile.MobileFormatter.Serialize(XmlWriter writer, Object graph)

  InnerException: 

Does anybody know why this is happening or what I might be doing wrong?  

RockfordLhotka replied on Thursday, September 02, 2010

Somehow your LinqObservableCollection is being referenced by a property/field in your object graph, and the serializer is trying to serialize that reference.

Smith866 replied on Friday, September 03, 2010

I have my LinqObservableCollection defined as a PropertyInfo on my root object as shown below.  Perhaps that is the problem?

 

private static readonly PropertyInfo<LinqObservableCollection<RmAdmin>> _rmAdminsHistoryProperty = RegisterProperty<LinqObservableCollection<RmAdmin>>(p => p.RmAdminsHistory);

        public LinqObservableCollection<RmAdmin> RmAdminsHistory

        {

            get

            {

 

                if (!FieldManager.FieldExists(_rmAdminsHistoryProperty))

                {

                    LazyLoadRmAdmin((o, e) =>

                {

                    var subset =  RmAdmins.ToSyncList(from n in RmAdmins where n.AdminStopDate != null select n);

                    LoadProperty(_rmAdminsHistoryProperty, subset );

                    OnPropertyChanged(_rmAdminsHistoryProperty);

                });

                }

                return GetProperty(_rmAdminsHistoryProperty);

            }

        }

RockfordLhotka replied on Friday, September 03, 2010

Yes, that is absolutely a problem. Properties can only reference serializable types, and LOC is not serializable - it is a volatile view over the real collection intended for use by the UI or other code.

Copyright (c) Marimer LLC