8
votes

Persister un Datacontract comme XML dans une base de données

Je travaille sur une application "magasin et transfert" pour les services de WCF. Je veux enregistrer le message dans une base de données en tant que blob de XML brut, en tant que xelement. J'ai un peu de difficulté à convertir le Datacontract dans le type de xelement dont j'ai besoin pour l'appel de la base de données. Des idées?


1 commentaires

Xélé n'est pas la même chose que "blob xml brut". Le premier est un type, pratique pour le faire avec XML. L'autre est une chaîne avec un format particulier. Vous pouvez économiser 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édenza, vous n'en avez pas besoin.


5 Réponses :


1
votes

Je ne suis pas sûr de la manière la plus efficace de l'obtenir à un xelement, mais de l'obtenir à une chaîne vient de courir:

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


0 commentaires

12
votes

Cela le renvoie comme une chaîne que vous pouvez mettre dans la DB dans une colonne XML. Voici une bonne méthode générique que vous pouvez utiliser pour sérialiser des données 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();
}


0 commentaires

2
votes

Si votre base de données est SQL Server 2005 ou plus, 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();
                }
            }
        }
    }
}


0 commentaires

1
votes

J'ai essayé d'utiliser la fonction Jason W'Serialize qui utilise StringBuilder, mais elle renvoie la chaîne vide pour la classe de table générée par Lingtosql. Avec [DataContract ()] Attribut

Toutefois, si je serialze à la matrice d'octet comme suggéré par Agilejon P>

puis utilisez UTF7CoDing pour convertir en chaîne, il crée une chaîne XML lisible. P>

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


0 commentaires

9
votes

Le plus voté sur la réponse (Jason W. Publié) n'a pas travaillé pour moi. Je ne sais pas pourquoi cette réponse a eu le plus de votes. Mais après avoir fouillé, j'ai trouvé ce

http://billrob.com/archive/2010/02/09/datacontractSerializer-converting-Objects-a-xml-string.aspx P>

qui a fonctionné pour mon projet. Je viens d'avoir quelques classes et de mettre les attributs DataContraitract et Datamemeber sur des classes et des propriétés, puis de recevoir une chaîne XML que je pouvais écrire dans la base de données. P>

code du lien ci-dessus, il va 404: p>

Serialises: P>

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 commentaires