2009-07-03 6 views
8

Je travaille sur une sorte d'application de stockage et de transfert pour les services WCF. Je veux enregistrer le message dans une base de données en tant que blob XML brut, comme XElement. J'ai un peu de mal à convertir le datacontract en le type XElement dont j'ai besoin pour l'appel de la base de données. Des idées?Conserver un contrat DataContract en tant que XML dans une base de données

+1

XElement n'est pas la même chose que "blob XML brut". Le premier est un type, pratique pour faire cela avec XML. L'autre est une chaîne avec un format particulier. Vous pouvez enregistrer à partir de n'importe quel type décoré avec [DataContract] dans la chaîne XML. (Voir ci-dessous pour des exemples). Le XElement - vous pouvez vous asseoir sur votre crédence, vous n'en avez pas besoin. – Cheeso

Répondre

12

cela, il revient en tant que chaîne, que vous pouvez mettre en le db dans une colonne xml. Voici une bonne méthode générique que vous pouvez utiliser pour sérialiser les contrats de données.

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, utilisez-vous linq à sql? La raison pour laquelle je demande est à cause de la partie XElement de votre question. Si c'est le cas, vous pouvez le modifier dans le concepteur .dbml pour utiliser une chaîne comme type CLR, et non XElement par défaut.

+0

Cela n'a pas fonctionné pour moi. Voir la réponse de user224125 ci-dessous. –

1

Je ne suis pas sûr de la façon la plus efficace pour obtenir un XElement, mais pour obtenir une chaîne à courir juste:

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

Si votre base de données est SQL Server 2005 ou au-dessus, vous pouvez utiliser le type de données 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

J'ai essayé d'utiliser la fonction Jason w'Serialize qui utilise StringBuilder, mais il retourne une chaîne vide pour LingToSQL Designer classe de table générée avec [DataContract()] attribut

Toutefois, si je serialze à tableau d'octets comme suggéré par AgileJon

puis utilisez UTF7Encoding pour convertir en chaîne, il crée chaîne XML lisible.

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

Vous ne savez pas pourquoi la solution stringBuilder ne fonctionne pas.

8

La réponse la plus votée (Jason W. posté) n'a pas fonctionné pour moi. Je ne sais pas pourquoi cette réponse a obtenu le plus de votes. Mais après la recherche autour J'ai trouvé ce

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

qui a travaillé pour mon projet. J'ai juste eu quelques classes et ai placé les attributs de datacontract et de datamemeber sur des classes et des propriétés et a voulu alors obtenir une chaîne XML que je pourrais écrire dans la base de données.

code à partir du lien ci-dessus Incase il va 404:

Sérialise:

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

Désérialise:

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

Merci pour le lien. –

Questions connexes