Life in my own company

Its all up to me.
posts - 137, comments - 166, trackbacks - 113

My Links

News



Twitter



Tag Cloud

Archives

Post Categories

Play

Work

Friday, August 15, 2008

Windows Vista Backup

O.k., I'll admit, the first time that I used windows Vista backup, I was very underwhelmed, but it's grown on me, and now I'm a huge fan.  On Monday, I received a new hard drive from Dell.  It's bigger and doesn't make strange clicking and stalling noises like the old drive did. :)  I was pretty certain that the old drive was going to go.

To swap out the drives, I plugged in a USB drive with sufficient capacity and did a windows backup complete pc backup.  Once that was finished, I plopped in the new drive and my Vista installation DVD.  After the restart, I selected the Restore Vista options, found my complete backup and started the restore.  Once it was done, I rebooted and was up and running again.  That was it!  It just worked!  I spent less than 10 minutes (not counting actual backup time) on completely replacing the drive.  I've NEVER had a backup and restore go that smoothly.  In the past, I've always had to install the OS before I could get to the backup, and then it'd be a hassle because of drivers and such, and the final restore wouldn't quite be the same.  This restored things EXACTLY the same.

I did have to reauthorize Diskeeper, but that was the only thing that I had to touch.

Knowing that I can mount the complete backup using virtual PC is also nice.

Technorati Tags: ,

posted @ Friday, August 15, 2008 4:39 PM | Feedback (1) |

WCF Serialization and the empty object bug

Ran into a serialization problem with WCF the other day that was rather interesting to find and fix.  It wasn't a problem with WCF, in the end, but rather with what we were telling WCF to do.

So we have some complex entities that we're shoving through the serialization layer.  We also send through lists of these entities, and the list may have references to itself.  To keep our list sizes small, we've implemented a DataContractSerializerOperationBehavior where when we create the data serializer, we set preserve references to true (it's just a variable below, but its set to true elsewhere):

        private static XmlObjectSerializer CreateDataContractSerializer(Type type, string name, string Notification Services, IList<Type> knownTypes)
        {
            return new DataContractSerializer
            (
                type, 
                name, 
                Notification Services, 
                knownTypes,
                maxItemsInObjectGraph /*maxItemsInObjectGraph*/,
                ignoreExtensionDataObject/*ignoreExtensionDataObject*/,
                preserveObjectReferences/*preserveObjectReferences*/,
                surrogate/*dataContractSurrogate*/
            );
        }

To make things more complicated, we have some custom lists of our entities that have properties on them.  As you may not know, when serializing a custom collection, the object is treated as a collection and any custom properties are ignored and are not serialized, even if you mark them as a DataMember.  Rather annoying.  To get around this, we implemented an IDataContractSurrogate, which you can see is passed into the data serializer above.  In GetObjectToSerialize method of the surrogate class that we created, we look to see what type we're trying to serialize and if it's one of our custom collections, we create a new instance of a surrogate that has an internal list, but is not a collection class itself, populate it with the contents and properties of the object that is to be serialized and then pass the surrogate back to the serializer.  Since our surrogate class is not a collection, WCF detects it correctly and serializes it correctly.  Then, on deserialization, we create a new instance of the collection, set it's properties, and then iterate through the surrogate's list and add the items to the new custom collections list.

Everything's happy, right?

Nope.  Our custom collection requires that objects of the same type are added to it.  The objects themselves have a Name that tells us what they are.  Our objects also have children that can be of the same type as the parent and are stored in the same type of class.  More precisely:

<Set>
    <SetItem Name="AParentThing">
        <Children>
            <Set>
                <SetItem Name="AChildThing">
                    <ParentSetItem ref="AParentThing[0]"></ParentSetItem>
                    ... (Perhaps even more sets and set items)
                </SetItem>
            </Set>
        </Children>
    </SetItem>
    <SetItem Name="AParentThing">
        ...(May have many layers)
    </SetItem>
</Set>

The problem appeared when we tried to serialize the cases where a child set referred back to a parent set.  We were getting weird errors, caused by the constraint that required that all items in a set be of the same type.  For some reason, the Name wasn't being serialized, or so we thought.  And what was weird is that it worked right most of the time, but then would occasionally fail, and what's worse, if we ignored the error, everything would work like we thought it should.  We were sure we'd just found a bug with WCF.

Turns out that name just hadn't YET be serialized.

I'm not sure about the order of serialization with data members, but it appears to be pretty arbitrary, unless you set the order on the data member.  We'd done two things incorrectly.  1.  We didn't set IsRequired on all of our DataMembers, and since this is a version 1 product, all of our interface elements should be present.  In future versions, maybe that'll change, but for now, they should all be there.  2.  We assumed that the deserialization of child collections wouldn't happen until after all of the members of the entity containing that collection were serialized, which is not the case.  As a result, the collections, which had a reference back to the parent, would attempt to deserialize BEFORE the name property had deserialized.

To fix, we changed all of our data members to look like this:

        [DataMember(Order=0, IsRequired = true)]

Note that order is 0 based.  At first, we only put the order property on the Name element, but that just caused it to fail every time, since WCF appears to serialize everything without an order first, then follow the order priority second.  After updating the other methods to also have an order, the problem has disappeared.  The name is always serialized first.  Note however, that even though the message contains the data, the resulting object may not contain the data.

Fun, Fun, Fun!

Technorati Tags: ,,

posted @ Friday, August 15, 2008 11:38 AM | Feedback (0) |

Powered by: