Persist a DataContract as XML in a database
Asked Answered
H

5

8

I'm working on a kind of "store and forward" application for WCF services. I want to save the message in a database as a raw XML blob, as XElement. I'm having a bit of trouble converting the datacontract into the XElement type I need for the database call. Any ideas?

Heinz answered 3/7, 2009 at 4:22 Comment(1)
XElement is not the same as "raw xml blob". The former is a type, handy for doing this with XML. The other is a string with a particular format. You can save from any type decorated with [DataContract] into XML string. (See below for examples). The XElement - you can sit that on your credenza, you don't need it.Hound
K
12

this returns it as a string, which you can put into the db into an xml column. Here is a good generic method you can use to serialize datacontracts.

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, are you using linq to sql? The reason i ask is because of the XElement part of your question. if thats the case, you can modify this in the .dbml designer to use a string as the CLR type, and not the default XElement.

Kiernan answered 3/7, 2009 at 4:37 Comment(0)
C
9

The most voted on answer (Jason W. posted) did not work for me. I dont know why that answer got the most votes. But after searching around I found this

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

Which worked for my project. I just had a few classes and put the datacontract and datamemeber attributes on classes and properties and then wanted to get an XML string which I could write to the database.

Code from the link above incase it goes 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;
}
Carbolated answered 1/12, 2010 at 18:48 Comment(0)
E
2

If your database is SQL Server 2005 or above, you can use the XML data type:

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();
                }
            }
        }
    }
}
Edrick answered 6/7, 2009 at 18:25 Comment(0)
C
1

I'm not sure about the most efficient way to get it to an XElement, but to get it to a string just run:

DataContractSerializer serializer = new DataContractSerializer(typeof(Foo));
using (MemoryStream memStream = new MemoryStream())
{
    serializer.WriteObject(memStream, fooInstance);
    byte[] blob = memStream.ToArray();
}
Cleisthenes answered 3/7, 2009 at 4:32 Comment(0)
P
1

I tried to use Jason w'Serialize function that uses StringBuilder , but it returns empty string for LingToSQL Designer generated table class with [DataContract()] attribute

However if I serialze to byte array as suggested by AgileJon

and then use UTF7Encoding to convert to string , it creates readable XML string.

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

Not sure why stringBuilder solution not working.

Playgoer answered 11/3, 2010 at 7:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.