C# Xml Serialization & Deserialization

40,757

Solution 1

In your deserialization code you're creating a MemoryStream and XmlTextWriter but you're not giving it the string to deserialize.

using (MemoryStream memStream = new MemoryStream())
{
    using (XmlTextWriter textWriter = new XmlTextWriter(memStream, Encoding.Unicode))
    {
        // Omitted
    }
}

You can pass the bytes to the memory stream and do away with the XmlTextWriter altogether.

using (MemoryStream memStream = new MemoryStream(Encoding.Unicode.GetBytes(xmlString)))
{
    System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
    return (T)serializer.Deserialize(memStream);
}

Solution 2

Looks like you got a handle on serializing to XML, so take my advice, store the XML in a string field (varchar, nvarchar, text, ntext) and not a specialized field.

If you do that little switch you will be ready to go... no further modification required.

XML field is subject to validations, and more than a few headaches, and if your application is only producer and consumer of that field, you might as well take that shortcut. SQL2008 (even 2005) is strong enough to compensate for the resources you might save by it compiling the xml field.

HOWEVER , I would optimize your code a bit, looks like you wrote way more code than you had to. For example, you no longer need to create a private field to store the data from your property, for example :

public PersonalXml Personal
{
    get { return _personal; }
    set { _personal = value; }
}

will work just fine if you wrote it like :

    public PersonalXml Personal { get ; set ; }

there's more fat you could have cut...

Share:
40,757
Skadoosh
Author by

Skadoosh

Updated on March 14, 2020

Comments

  • Skadoosh
    Skadoosh about 4 years

    I am trying to serialize an object & save it into a Sql server 2008 xml field. I also have some deserialization code that re-hydrates the object. I am able to serialize & save the object into the db, but get a "Root element missing" exception.

    [XmlRoot("Patient")]
    public class PatientXml
    {
        private AddressXml _address = null;
        private EmergencyContactXml _emergencyContact = null;
        private PersonalXml _personal = null;
    
        [XmlElement]
        public PersonalXml Personal
        {
            get { return _personal; }
            set { _personal = value; }
        }
    
        [XmlElement]
        public AddressXml Address
        {
            get { return _address; }
            set { _address = value; }
        }
    
        [XmlElement]
        public EmergencyContactXml EmergencyContact
        {
            get { return _emergencyContact; }
            set { _emergencyContact = value; }
        }
    
        public PatientXml(){}
        public PatientXml(Patient patient)
        {
            _address = new AddressXml(patient.Address);
            _emergencyContact = new EmergencyContactXml(patient.EmergencyInfo);
            _personal = new PersonalXml(patient);
        }
    }
    
    public class PersonalXml
    {
        private string _firstName = string.Empty, _lastName = string.Empty, _dateOfBirth = string.Empty, _phone = string.Empty;
    
        [XmlAttribute]
        public string FirstName
        {
            get { return _firstName; }
            set { _firstName = value; }
        }
    
        [XmlAttribute]
        public string LastName
        {
            get { return _lastName; }
            set { _lastName = value; }
        }
    
        [XmlAttribute]
        public string DateOfBirth
        {
            get { return _dateOfBirth; }
            set { _dateOfBirth = value; }
        }
    
        [XmlAttribute]
        public string Phone
        {
            get { return _phone; }
            set { _phone = value; }
        }
    
        public PersonalXml(){}
        public PersonalXml(Patient patient)
        {
            _firstName = patient.FirstName;
            _lastName = patient.LastName;
            _dateOfBirth = patient.DateOfBirth.ToShortDateString();
            _phone = patient.Phone;
        }
    }
    
    public class AddressXml
    {
        private string _address1 = string.Empty, _address2 = string.Empty, _city = string.Empty, _state = string.Empty, _zip = string.Empty;
    
        [XmlAttribute]
        public string Address1
        {
            get { return _address1; }
            set { _address1 = value; }
        }
    
        [XmlAttribute]
        public string Address2
        {
            get { return _address2; }
            set { _address2 = value; }
        }
    
        [XmlAttribute]
        public string City
        {
            get { return _city; }
            set { _city = value; }
        }
    
        [XmlAttribute]
        public string State
        {
            get { return _state; }
            set { _state = value; }
        }
    
        [XmlAttribute]
        public string Zip
        {
            get { return _zip; }
            set { _zip = value; }
        }
    
        public AddressXml(){}
        public AddressXml(Address address)
        {
            _address1 = address.Address1;
            _address2 = address.Address2;
            _city = address.City;
            _state = address.State;
            _zip = address.ZipCode;
        }
    }
    
    public class EmergencyContactXml
    {
        private string _name = string.Empty, _phone = string.Empty, _relationship = string.Empty;
    
        [XmlAttribute]
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
    
        [XmlAttribute]
        public string Phone
        {
            get { return _phone; }
            set { _phone = value; }
        }
    
        [XmlAttribute]
        public string Relationship
        {
            get { return _relationship; }
            set { _relationship = value; }
        }
    
        public EmergencyContactXml(){}
        public EmergencyContactXml(EmergencyContact contact)
        {
            _name = contact.ContactName;
            _phone = contact.Phone;
            _relationship = contact.Relationship;
        }
    }
    

    Serialized Xml output:

    <Patient 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <Personal FirstName="Test" LastName="User 1" DateOfBirth="3/13/1966" Phone="6304449866" />
        <Address Address1="123 Some St" City="Bartlett" State="CT" Zip="60111" />
        <EmergencyContact Name="Dr Chanduwarthana" Phone="6309769484" Relationship="Father" />
    </Patient>
    

    Serization & Deserialization code:

    public static class XmlSerializer
    {
        public static string Serialize<T>(T item)
        {
            MemoryStream memStream = new MemoryStream();
            using (XmlTextWriter textWriter = new XmlTextWriter(memStream, Encoding.Unicode))
            {
                System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
                serializer.Serialize(textWriter, item);
    
                memStream = textWriter.BaseStream as MemoryStream;
            }
            if (memStream != null)
                return Encoding.Unicode.GetString(memStream.ToArray());
            else
                return null;
        }
    
        public static T Deserialize<T>(string xmlString)
        {
            if (string.IsNullOrWhiteSpace(xmlString))
                return default(T);
    
            using (MemoryStream memStream = new MemoryStream())
            {
                using (XmlTextWriter textWriter = new XmlTextWriter(memStream, Encoding.Unicode))
                {
                    memStream.Position = 0;
                    System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
                    return (T)serializer.Deserialize(memStream);
                }
            }
        }
    }
    
  • Skadoosh
    Skadoosh over 12 years
    how do I do that? The XML code was generated when I serialized the object.
  • competent_tech
    competent_tech over 12 years
    You should be able to add it to the output of the serialize method.
  • Skadoosh
    Skadoosh over 12 years
    I thought that the xml field in sql server 2008 is more optimized for xml query. Or can I also use other fields like varchar, nvarchar, etc?
  • Skadoosh
    Skadoosh over 12 years
    That worked!! Just curious ... what was going on with the TextWriter?
  • Dave Fancher
    Dave Fancher over 12 years
    @KP. The XmlTextWriter isn't necessary for deserialization since you're not building any XML. In this case it was created with a reference to the MemoryStream and instructed to use Unicode but wasn't referenced beyond its creation. I also noticed that the MemoryStream in the serialization code isn't disposed. You should probably consider revising the code to wrap it in a using block as well.