2012-01-04 32 views
11

オブジェクトをシリアル化しようとしています& Sql server 2008 xmlフィールドに保存します。オブジェクトを再水和する逆シリアル化コードもあります。私は&をdbにオブジェクトを保存することができますが、 "ルート要素がありません"という例外を得ることができます。C#Xmlシリアル化と逆シリアル化

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

直列化されたXML出力:

<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 &デシリアライズコード:

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

あなたがクーロン:私はあなたがXMLヘッダーを追加する必要があると信じてい

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

答えて

11

:Dこれが追加される原因となるオプションのパラメータを受け入れるようにあなたのSerializeメソッドを変更します。

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

メモリストリームにバイトを渡して、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

それはうまくいった!ただ興味があります... TextWriterでは何が起こっていましたか? – Skadoosh

+2

@KP。 XmlTextWriterは、XMLを構築していないため、逆シリアル化には必要ありません。この場合は、MemoryStreamへの参照で作成され、Unicodeを使用するよう指示されましたが、作成を超えて参照されませんでした。 シリアル化コード内のMemoryStreamが破棄されていないことにも気付きました。おそらくコードを改訂して、それを使用ブロックにラップすることも考慮する必要があります。 –

0

あなたはMemoryStreamをとてXmlTextWriterを作成しているが、あなたはそれをデシリアライズする文字列を与えていない、あなたのデシリアライゼーションのコードでは

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

どうすればいいですか? XMLコードは、オブジェクトをシリアライズするときに生成されました。 – Skadoosh

+0

これをserializeメソッドの出力に追加できるはずです。 –

1

あなたがXMLにシリアライズのハンドルを持っているように見えますので、文字列フィールド(varchar型、nvarchar型、テキスト、ntext型)およびない専門分野でXMLを格納し、私のアドバイスを取ります。

この小さなスイッチを使用すると、準備が整います。これ以上の変更は必要ありません。

XMLフィールドは検証の対象となり、いくつかの頭痛があります。アプリケーションがそのフィールドのプロデューサとコンシューマだけの場合は、そのショートカットを使用することもできます。 SQL2008(2005も)は、xmlフィールドをコンパイルすることで節約できるリソースを補うほど強力です。

HOWEVER、 私はあなたのコードを少し最適化しました。あなたがしなければならないより多くのコードを書いたようです。 たとえば、あなたはもはや、たとえば、あなたの財産からのデータを格納するためのプライベートフィールドを作成する必要があります。

public PersonalXml Personal { get ; set ; } 

をより多くがあります:

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

は、あなたがそれを書いた場合は好きなだけで正常に動作します脂肪を減らすことができました...

+0

私は、SQL Server 2008のXMLフィールドは、XMLクエリの方がより最適化されていると考えました。または、varchar、nvarcharなどの他のフィールドも使用できますか? – Skadoosh