2009-07-03 3 views
8

Sto lavorando a un tipo di applicazione "store and forward" per i servizi WCF. Voglio salvare il messaggio in un database come un blob XML grezzo, come XElement. Sto avendo un po 'di problemi a convertire il datacontract nel tipo XElement di cui ho bisogno per la chiamata al database. Qualche idea?Persist un DataContract come XML in un database

+1

XElement non è lo stesso di "blob XML grezzo". Il primo è un tipo, utile per farlo con XML. L'altro è una stringa con un formato particolare. Puoi salvare da qualsiasi tipo decorato con [DataContract] nella stringa XML. (Vedi sotto per gli esempi). The XElement: puoi sederti sulla tua credenza, non ne hai bisogno. – Cheeso

risposta

12

questo restituisce come una stringa, che si può mettere in il db in una colonna xml. Ecco un buon metodo generico che è possibile utilizzare per serializzare i contratti di dati.

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, stai utilizzando linq per sql? Il motivo per cui lo chiedo è a causa della parte XElement della tua domanda. Se questo è il caso, puoi modificarlo nel designer .dbml per usare una stringa come tipo CLR, e non il predefinito XElement.

+0

Questo non ha funzionato per me. Vedere la risposta dell'utente224125 di seguito. –

1

io non sono sicuro circa il modo più efficiente per arrivare a un XElement, ma per ottenere una stringa appena eseguito:

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

Se il database è SQL Server 2005 o superiore, è possibile utilizzare il tipo di dati 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

Ho cercato di usare la funzione Jason w'Serialize che utilizza StringBuilder, ma restituisce una stringa vuota per LingToSQL Designer generato classe tavolo con la stringa XML leggibile [DataContract()] attributo

Tuttavia, se mi serialze di array di byte, come suggerito dal AgileJon

e quindi utilizzare UTF7Encoding per convertire in stringa, che crea.

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

Non so perché la soluzione stringBuilder non funzioni.

8

La risposta più votata (Jason W. pubblicato) non ha funzionato per me. Non so perché quella risposta ha ottenuto il maggior numero di voti. Ma dopo la ricerca intorno ho trovato questo

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

che ha lavorato per il mio progetto. Ho appena avuto alcune classi e ho inserito gli attributi datacontract e datamemeber su classi e proprietà e poi ho voluto ottenere una stringa XML che potrei scrivere nel database.

codice dal link qui sopra in caso si va 404:

Serializza:

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

deserializza:

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

Grazie per il link. –