2012-01-04 18 views
11

estoy tratando de serializar un objeto & guardarlo en un campo XML de SQL Server 2008. También tengo un código de deserialización que rehidrata el objeto. Puedo serializar & guardar el objeto en el archivo db, pero aparece la excepción "Root element missing".C# serialización XML y deserialización

[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; 
    } 
} 

Serializado salida XML: Código

<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 & Deserialización:

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); 
      } 
     } 
    } 
} 

Respuesta

11

En su código deserialización se está creando un MemoryStream y XmlTextWriter pero no estás dándole la cadena deserializar.

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

Puede pasar los bytes a la secuencia de memoria y eliminar por completo el XmlTextWriter.

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); 
} 
+1

¡Eso funcionó! Solo curiosidad ... ¿Qué estaba pasando con el TextWriter? – Skadoosh

+2

@KP. XmlTextWriter no es necesario para la deserialización, ya que no está compilando ningún XML. En este caso, se creó con una referencia a MemoryStream y se le indicó que utilizara Unicode, pero no se hizo referencia más allá de su creación. También noté que el MemoryStream en el código de serialización no está eliminado. Probablemente deberías considerar revisar el código para envolverlo también en un bloque de uso. –

0

Creo que es necesario agregar el encabezado XML:

<?xml version="1.0" encoding="utf-8" ?> 

Usted COUL d modificar su método de serialización para aceptar un parámetro opcional que causaría que esto se añadió:

public static string Serialize<T>(T item, bool includeHeader = false) 
{ 
    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) 
     if (includeHeader) 
     { 
      return @"<?xml version=""1.0"" encoding=""utf-8"" ?>" + Environment.NewLine + Encoding.Unicode.GetString(memStream.ToArray()); 
     } 
     else 
     { 
      return Encoding.Unicode.GetString(memStream.ToArray()); 
     } 
    else 
     return null; 
} 
+0

cómo lo hago? El código XML se generó cuando serialicé el objeto. – Skadoosh

+0

Debería poder agregarlo al resultado del método de serialización. –

1

Parece que tienes una manija en la serialización de XML, así que mi consejo, almacenar el XML en un campo de cadena (varchar, nvarchar, texto, ntext) y no un campo especializado.

Si lo hace pequeño interruptor que estará listo para ir ... sin modificación adicional necesaria.

campo XML está sujeta a las validaciones, y más de un dolor de cabeza, y si su aplicación es el único productor y consumidor de ese campo, que también podría tomar ese atajo. SQL2008 (incluso 2005) es lo suficientemente fuerte como para compensar los recursos que podría ahorrar al compilar el campo xml.

SIN EMBARGO, Optimizo un poco tu código, parece que escribiste mucho más código del que tenías que hacer. Por ejemplo, ya no es necesario para crear un campo privado para almacenar los datos de su propiedad, por ejemplo:

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

funcionará bien si usted lo escribió como:

public PersonalXml Personal { get ; set ; } 

hay más la grasa se podría haber cortado ...

+0

Pensé que el campo xml en sql server 2008 está más optimizado para consultas XML. ¿O también puedo usar otros campos como varchar, nvarchar, etc.? – Skadoosh

Cuestiones relacionadas