2009-07-03 21 views
8

Pracuję nad pewnego rodzaju aplikacji "przechowywania i przekazywania" dla usług WCF. Chcę zapisać wiadomość w bazie danych jako surowy blob XML, tak jak XElement. Mam problem z konwertowaniem datacontract na typ XElement, którego potrzebuję do wywołania bazy danych. Jakieś pomysły?Trwałe DataContract jako XML w bazie danych

+1

Xelement nie jest taka sama jak "surowego xml blob". Ten pierwszy jest typem, przydatnym do tego przy pomocy XML. Drugi to ciąg o określonym formacie. Możesz zapisać w dowolnym typie ozdobionym [DataContract] ciągiem XML. (Zobacz przykłady poniżej). XElement - możesz usiąść na swojej credenzie, nie potrzebujesz tego. – Cheeso

Odpowiedz

12

ta zwraca go jako ciąg znaków, który można umieścić w db do kolumny xml. Oto dobra ogólna metoda, której możesz użyć do serializowania danych na serwerze.

public static string Serialize<T>(T obj) 
{ 
    StringBuilder sb = new StringBuilder(); 
    DataContractSerializer ser = new DataContractSerializer(typeof(T)); 
    ser.WriteObject(XmlWriter.Create(sb), obj); 
    return sb.ToString(); 
} 

btw, czy używasz linq do sql? Powód, dla którego pytam, jest spowodowany częścią XElement twojego pytania. Jeśli tak jest, możesz zmodyfikować to w projektancie .dbml, aby użyć ciągu znaków jako typu CLR, a nie domyślnego XElement.

+0

To nie działa dla mnie. Zobacz odpowiedź użytkownika224125 poniżej. –

1

nie jestem pewien co najbardziej efektywny sposób, aby dostać się do Xelement, ale aby dostać się do łańcucha wystarczy uruchomić:

DataContractSerializer serializer = new DataContractSerializer(typeof(Foo)); 
using (MemoryStream memStream = new MemoryStream()) 
{ 
    serializer.WriteObject(memStream, fooInstance); 
    byte[] blob = memStream.ToArray(); 
} 
2

Jeśli baza danych jest SQL Server 2005 lub nowszy, można użyć typu danych XML:

private readonly DataContractToSerialize _testContract = 
    new DataContractToSerialize 
     { 
      ID = 1, 
      Name = "One", 
      Children = 
       { 
        new ChildClassToSerialize {ChildMember = "ChildOne"}, 
        new ChildClassToSerialize {ChildMember = "ChildTwo"} 
       } 
     }; 

public void SerializeDataContract() 
{ 
    using (var outputStream = new MemoryStream()) 
    { 
     using (var writer = XmlWriter.Create(outputStream)) 
     { 
      var serializer = 
       new DataContractSerializer(_testContract.GetType()); 
      if (writer != null) 
      { 
       serializer.WriteObject(writer, _testContract); 
      } 
     } 

     outputStream.Position = 0; 
     using (
      var conn = 
       new SqlConnection(Settings.Default.ConnectionString)) 
     { 
      conn.Open(); 

      const string INSERT_COMMAND = 
       @"INSERT INTO XmlStore (Data) VALUES (@Data)"; 
      using (var cmd = new SqlCommand(INSERT_COMMAND, conn)) 
      { 
       using (var reader = XmlReader.Create(outputStream)) 
       { 
        var xml = new SqlXml(reader); 

        cmd.Parameters.Clear(); 
        cmd.Parameters.AddWithValue("@Data", xml); 
        cmd.ExecuteNonQuery(); 
       } 
      } 
     } 
    } 
} 
1

Próbowałem użyć funkcji Jason w'Serialize który używa StringBuilder, ale zwraca pusty ciąg dla LingToSQL Designer wygenerowane klasy stół z [DataContract()] przypisują

jednak gdybym serialze do tablicy bajtów jak sugeruje AgileJon

a następnie użyć UTF7Encoding przekonwertować ciąg tworzy czytelnego ciągu XML.

static string DataContractSerializeUsingByteArray<T>(T obj) 
    { 
     string sRet = ""; 
     DataContractSerializer serializer = new DataContractSerializer(typeof(T)); 
     using (MemoryStream memStream = new MemoryStream()) 
     { 
      serializer.WriteObject(memStream, obj); 
      byte[] blob = memStream.ToArray(); 
      var encoding= new System.Text.UTF7Encoding(); 
      sRet = encoding.GetString(blob); 
     } 
     return sRet; 
    } 

Nie wiem, dlaczego rozwiązanie StringBuilder nie działa.

8

Najbardziej głosowana na odpowiedź (Jason W. opublikowane) nie działa dla mnie. Nie wiem, dlaczego ta odpowiedź ma najwięcej głosów. Ale po poszukiwaniach wokół znalazłem to

http://billrob.com/archive/2010/02/09/datacontractserializer-converting-objects-to-xml-string.aspx

która pracowała dla mojego projektu. Właśnie miałem kilka klas i umieściłem dataceme i atrybuty datamemeber na klasach i właściwościach, a następnie chciałem uzyskać łańcuch XML, który mógłbym napisać do bazy danych.

kod z linku powyżej okrywać idzie 404:

Serializes:

var serializer = new DataContractSerializer(tempData.GetType()); 
using (var backing = new System.IO.StringWriter()) 
using (var writer = new System.Xml.XmlTextWriter(backing)) 
{ 
    serializer.WriteObject(writer, tempData); 
    data.XmlData = backing.ToString(); 
} 

Deserializes:

var serializer = new DataContractSerializer(typeof(T)); 
using (var backing = new System.IO.StringReader(data.XmlData)) 
using (var reader = new System.Xml.XmlTextReader(backing)) 
{ 
    return serializer.ReadObject(reader) as T; 
} 
+0

Dzięki za link. –

Powiązane problemy