2009-07-03 17 views
8

Estoy trabajando en una especie de aplicación "store and forward" para servicios WCF. Quiero guardar el mensaje en una base de datos como un blob XML sin formato, como XElement. Estoy teniendo problemas para convertir el contrato de datos en el tipo XElement que necesito para la llamada a la base de datos. ¿Algunas ideas?Persista un DataContract como XML en una base de datos

+1

XElement no es lo mismo que "blob XML sin procesar". El primero es un tipo, útil para hacer esto con XML. El otro es una cadena con un formato particular. Puede guardar desde cualquier tipo decorado con [DataContract] en cadenas XML. (Ver abajo para ejemplos). El XElement: puedes sentarte en tu credenza, no lo necesitas. – Cheeso

Respuesta

12

Esto devuelve como una cadena, que se puede poner en el db en una columna xml Aquí hay un buen método genérico que puede usar para serializar los contactos de datos.

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, ¿estás usando linq en sql? La razón por la que pregunto es por la parte XElement de su pregunta. si ese es el caso, puede modificar esto en el diseñador de .dbml para usar una cadena como el tipo CLR, y no el XElement predeterminado.

+0

Esto no funcionó para mí. Ver la respuesta de user224125 a continuación. –

1

No estoy seguro acerca de la forma más eficiente para llegar a un XElement, pero para llegar a una cadena acaba de correr:

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

Si su base de datos es SQL Server 2005 o superior, se puede utilizar el tipo de datos 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

He intentado utilizar la función Jason w'Serialize que utiliza StringBuilder, pero devuelve cadena vacía para LingToSQL diseñador generada clase mesa con una cadena XML legible [DataContract()] atribuir

Sin embargo si serialze de matriz de bytes según lo sugerido por AgileJon

y luego usar UTF7Encoding para convertir a cadena, se 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; 
    } 

No estoy seguro de por qué la solución de stringBuilder no funciona.

8

La respuesta más votada (Jason W. publicado) no funcionó para mí. No sé por qué esa respuesta obtuvo la mayoría de los votos. Pero después de buscar en torno encontré este

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

que funcionó para mi proyecto. Acabo de tener algunas clases y poner los atributos de contrato de datos y datamemeber en clases y propiedades y luego quería obtener una cadena XML que podía escribir en la base de datos.

Código desde el enlace de arriba en caso que se va 404:

Serializa:

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

Deserializa:

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

Gracias por el enlace. –

Cuestiones relacionadas