none
deserializing POCO object graphs serialized with IsReference=true does not build up the whole objectgraph RRS feed

  • Question

  • Hi here,

    we are using an adapted MS standard POCO T4 Template. Its extented with DataContracts(IsReference=true), Datamembers and KnownTypes decorations. We send the modified POCOS over with WCF. Serialisation works fine whereas Deserialisation does not build up the objectgraph properly. We are just missing some references. All though the serialized data looks ok.

    Anyone having issues with deserializing objectgraphs serialized with IsReference=true?
    Why are the references exiting in the serialized data not build up into some correspondent objectgraph?

    Best regards

    David


    Here are some further explanations:

    We have a hierarchy as following:

        Cassette
            Bottle

    ·         Cassette 1:n Bottle

    We have a ServiceContract which gives back a customised DTO BookingResultDto which contains a list of bottles.
        [DataContract]
        public class BookingResultDto
        {
                [DataMember]
           public ResourceBookingDto ResourceBooking { get; protected set; }

    **************

    [DataContract]

        public class ResourceBookingDto

        {

                [DataMember]

            private List<ResourceBookingItemDto> bookingItems = new List<ResourceBookingItemDto>();

    **************

    [DataContract]

        public class ResourceBookingItemDto

        {

            [DataMember]

            public Bottle Bottle { get; set; }

    ***************

        [DataContract(IsReference = true)]

        [KnownType(typeof(Cassette))]

        public partial class Bottle
           {
            
    [DataMember]

            public Cassette Cassette

            {

     

    **********

     

        [DataContract(IsReference = true)]

        [KnownType(typeof(Bottle))]

        [KnownType(typeof(ResourceSet))]

        public partial class Cassette

    {
     [DataMember]

            public ICollection<Bottle> Bottles

            {

     

    Serialisation works fine. the produced xml looks ok. A sample is attached. The serialized DTO contains 2 ResourceBookingItemDto each containing a distinct bottle belonging to the same cassette. 

    Deserialisation fills the first Bottle with Cassette.
    The second Bottle is then created but now no reference to the cassette is being deserialized. Since both bottles are referenced by the same Cassette on server side, it would be only required to set the Cassette Reference of the second bottle to the already instantiated Cassette. But this does not happen.

    Here is the deserialization code:

          DataContractSerializer serializer = new DataContractSerializer(typeof(BookingResultDto));

                using (MemoryStream ms = new MemoryStream())

                {

                    serializer.WriteObject(ms, dto);

                    ms.Flush();

                    ms.Seek(0, SeekOrigin.Begin);

                    BookingResultDto resultDto = serializer.ReadObject(ms) as BookingResultDto;

                    Assert.IsNotNull(resultDto);

                    Assert.IsNotNull(resultDto.ResourceBooking.BookingItems.ElementAt(0).Bottle.Cassette);

                    Assert.IsNotNull(resultDto.ResourceBooking.BookingItems.ElementAt(1).Bottle.Cassette);

                }

    The second Assert always fails. We tried even to initialize DataContractSerializers with PreserveObjectreferences, but that did not work.

     

    <BookingResultDto xmlns:i="http://www.w3.org/2001/XMLSchema-instance" z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" xmlns="http://schemas.datacontract.org/2004/07/Roche.C4C.ResourceManagement.Interfaces">
      <ResourceBooking z:Id="i2">
        <ResourceBookingId xmlns:d3p1="http://schemas.datacontract.org/2004/07/Roche.C4C.Common.DataAccess">
          <d3p1:value>0</d3p1:value>
        </ResourceBookingId>
        <bookingItems>
          <ResourceBookingItemDto z:Id="i3">
            <Bottle xmlns:d5p1="http://schemas.datacontract.org/2004/07/Roche.C4C.DataAccess.Resources.Domain" z:Id="i4">
              <d5p1:BottleIdDb>1</d5p1:BottleIdDb>
              <d5p1:BottleTypeValueDb>5</d5p1:BottleTypeValueDb>
              <d5p1:Cassette z:Id="i5">
                <d5p1:BarcodeExpDateDb>2012-02-01T00:00:00</d5p1:BarcodeExpDateDb>
                <d5p1:BlockedReasonsDb>0</d5p1:BlockedReasonsDb>
                <d5p1:Bottles>
                  <d5p1:Bottle z:Id="i6">
                    <d5p1:BottleIdDb>2</d5p1:BottleIdDb>
                    <d5p1:BottleTypeValueDb>2</d5p1:BottleTypeValueDb>
                    <d5p1:Cassette z:Ref="i5" />
                    <d5p1:CassetteIdDb>1</d5p1:CassetteIdDb>
                    <d5p1:NumberOfTestsDb i:nil="true" />
                    <d5p1:PositionValueDb>3</d5p1:PositionValueDb>
                    <d5p1:ReagentTypeValueDb>6</d5p1:ReagentTypeValueDb>
                    <d5p1:StatusDb>5</d5p1:StatusDb>
                    <d5p1:VolumeDb>3800</d5p1:VolumeDb>
                  </d5p1:Bottle>
                  <d5p1:Bottle z:Ref="i4" />
                </d5p1:Bottles>
                <d5p1:CassetteIdDb>1</d5p1:CassetteIdDb>
                <d5p1:CassetteTypeDb>2</d5p1:CassetteTypeDb>
                <d5p1:ContainerCodeDb>4050</d5p1:ContainerCodeDb>
                <d5p1:ContainerTypeDb>3</d5p1:ContainerTypeDb>
                <d5p1:ExpirationDateDb>0001-01-01T00:00:00</d5p1:ExpirationDateDb>
                <d5p1:LastUsedDb>0001-01-01T00:00:00</d5p1:LastUsedDb>
                <d5p1:LockedDb>false</d5p1:LockedDb>
                <d5p1:LotDb>123</d5p1:LotDb>
                <d5p1:PModuleIdDb>910</d5p1:PModuleIdDb>
                <d5p1:PModuleSubPositionDb>1</d5p1:PModuleSubPositionDb>
                <d5p1:ReagentSets />
                <d5p1:ReconstitutionOrders />
                <d5p1:RegisterDateDb>0001-01-01T00:00:00</d5p1:RegisterDateDb>
                <d5p1:ResourceSets />
                <d5p1:SerialNumberDb>161</d5p1:SerialNumberDb>
                <d5p1:StatusDb>0</d5p1:StatusDb>
              </d5p1:Cassette>
              <d5p1:CassetteIdDb>1</d5p1:CassetteIdDb>
              <d5p1:NumberOfTestsDb i:nil="true" />
              <d5p1:PositionValueDb>1</d5p1:PositionValueDb>
              <d5p1:ReagentTypeValueDb>1</d5p1:ReagentTypeValueDb>
              <d5p1:StatusDb>5</d5p1:StatusDb>
              <d5p1:VolumeDb>18000</d5p1:VolumeDb>
            </Bottle>
            <ReservedAmount xmlns:d5p1="http://schemas.datacontract.org/2004/07/Roche.C4C.Common.DomainSupport">
              <d5p1:value>99</d5p1:value>
            </ReservedAmount>
          </ResourceBookingItemDto>
          <ResourceBookingItemDto z:Id="i7">
            <Bottle xmlns:d5p1="http://schemas.datacontract.org/2004/07/Roche.C4C.DataAccess.Resources.Domain" z:Ref="i6" />
            <ReservedAmount xmlns:d5p1="http://schemas.datacontract.org/2004/07/Roche.C4C.Common.DomainSupport">
              <d5p1:value>38</d5p1:value>
            </ReservedAmount>
          </ResourceBookingItemDto>
        </bookingItems>
      </ResourceBooking>
    </BookingResultDto>
    

     


    More of myself: http://www.richter-web.info
    Tuesday, December 20, 2011 1:04 PM

Answers

  • Hi Urpcor,

    Thanks for your feedback. I can repro your scenario now.

     

    [DataContract] //remove IsReference=true
    public partial class Bottle
            {
             [DataMember(IsRequired=true)]
     
            public Cassette Cassette
     
            {
    }}


    It seems to work on my computer.

     

    Have a nice day.


    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.


    Tuesday, December 27, 2011 8:24 AM
    Moderator

All replies

  • Hi UrpCor,

    >>resultDto.ResourceBooking.BookingItems.ElementAt(1).Bottle.Cassette

    ElementAt(1) as follows in your xml:

    <ResourceBookingItemDto z:Id="i7">
            <Bottle xmlns:d5p1="http://schemas.datacontract.org/2004/07/Roche.C4C.DataAccess.Resources.Domain" z:Ref="i6" />
            <ReservedAmount xmlns:d5p1="http://schemas.datacontract.org/2004/07/Roche.C4C.Common.DomainSupport">
              <d5p1:value>38</d5p1:value>
            </ReservedAmount>
          </ResourceBookingItemDto>
    

    There is not Bottle.Cassette, the deserializer couldn't find the source. I think your problem may relates to Serialisation.

    Have a nice day.

     


    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Friday, December 23, 2011 4:00 AM
    Moderator
  • As I understand the serialisation is with references.

    Element(1) is a reference to a Bottle

    z:Ref="i6"
    And if one looks in the serialised data there is a Bottle with
    z:Ref="i6" pointing to a cassette:
    <d5p1:Cassette z:Id="i5"> <d5p1:BarcodeExpDateDb>2012-02-01T00:00:00</d5p1:BarcodeExpDateDb> <d5p1:BlockedReasonsDb>0</d5p1:BlockedReasonsDb> <d5p1:Bottles> <d5p1:Bottle z:Id="i6"> <d5p1:BottleIdDb>2</d5p1:BottleIdDb> <d5p1:BottleTypeValueDb>2</d5p1:BottleTypeValueDb> <d5p1:Cassette z:Ref="i5" /> <d5p1:CassetteIdDb>1</d5p1:CassetteIdDb>

    So in my Opinion the serialised data is ok. it should get deserialised properly.

    More of myself: http://www.richter-web.info
    Friday, December 23, 2011 8:20 AM
  • Hi Urpcor,

    I'm not sure about your class, but from the XML structure, i think there may some misunderstanding here:

    Have a nice day.


    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Friday, December 23, 2011 9:10 AM
    Moderator
  • Hi Alan,

    Thank you for looking into it.

    Yes there are 2 Items but they refer to objects either to the real one or one reference. but I presume the references are global for the whole xml result.

    From the second item the bottle get deserialized quite well despite being only a reference z:Ref="i6"

    Only the reference to the cassette is not being set all though bottle from item 1 has the same cassette.

    Or am I wrong in my presumptions concerning Serializing with references?

    Thanks for any hint


    More of myself: http://www.richter-web.info
    Friday, December 23, 2011 12:04 PM
  • Hi Urpcor,

    Thanks for your feedback. I can repro your scenario now.

     

    [DataContract] //remove IsReference=true
    public partial class Bottle
            {
             [DataMember(IsRequired=true)]
     
            public Cassette Cassette
     
            {
    }}


    It seems to work on my computer.

     

    Have a nice day.


    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.


    Tuesday, December 27, 2011 8:24 AM
    Moderator