views:

116

answers:

5

I would like to save an instance of a c#.NET class in SQL for later retrieval. I am able to use LINQ to SQL to add a record complete with all the xml that makes up the class.

Now how do I retrieve that xml and reconstruct the class object instance?

A: 

I would recommend xml serialization and deserialization.

If I have a class Person defined with:

public class Person
{
    public int ID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfBirth { get; set; }
}

saving it/loading it from XML is as simple as:

Person donald = new Person{
                ID=1, 
                FirstName="Donald", 
                LastName="Duck", 
                DateOfBirth=new DateTime(1950,1,1)};

//create a xml serializer with the required type
XmlSerializer xs=new XmlSerializer(typeof(Person));

//open a stream to the file, and save the instance
TextWriter tw = new StreamWriter(@"C:\donald.xml");
xs.Serialize(tw, donald);
tw.Close();

//open a reader stream to the file, and just load the instance.
TextReader tr = new StreamReader(@"C:\donald.xml");
Person donald2 = (Person) xs.Deserialize(tr);
tr.Close();

Caveat: This saves only the public properties/fields of a class, as XML Elements. If you want to exercise addition control over the generated XML, take a look at the attributes in the System.Xml.Serialization namespace (XmlAttributeAttribute is my personal favorite),

SWeko
-1 for not using a `using` block around the `StreamReader`.
John Saunders
Well I'm closing the readers/writers explicitly :)It's intentional, since I don't like using `using` when I declare variables inside the using block, it makes the code less readable.
SWeko
A: 

You might want to use XStream to store the object as XML. It's pretty easy to use.

npinti
+5  A: 

Serialize your object to an XML string:

    public static string ToXml<T>(T obj)
    {
        XmlWriterSettings settings = new XmlWriterSettings();

        settings.OmitXmlDeclaration = true;
        using (Stream stream = new MemoryStream())
        using (XmlWriter writer = XmlWriter.Create(stream, settings))
        {
            new XmlSerializer(obj.GetType()).Serialize(writer, obj);
            writer.Flush();
            stream.Flush();
            stream.Position = 0;
            using (TextReader reader = new StreamReader(stream))
            {
                return reader.ReadToEnd();
            }
        }
    }

Deserialize an XML string into an object:

    public static T FromXml<T>(string xml)
    {
        using (TextReader reader = new StringReader(xml))
        {
            try
            {
                return (T)new XmlSerializer(typeof(T)).Deserialize(reader);
            }
            catch (InvalidOperationException)
            {
                // string passed is not XML, return default
                return default(T);
            }
        }
    }
Jesse C. Slicer
Great answer Jesse. Thanks for your help on this!
mcass20
@mcass20, you're very welcome. Always a pleasure to share code and techniques.
Jesse C. Slicer
+2  A: 

As others mention, serialization will do the trick, but be aware of the formatters/serializer, otherwise this :

<?xml version="1.0" encoding="utf-8" ?>

will be part of your serialization. Whenever possible, use the DataContractSerializer.

I highly recommend you to see this : http://stackoverflow.com/questions/933664/net-xml-serialization-without-xml-root-node before doing anything.

HTH

Markust
A: 

Check out OXM which is a POCO approach to do xml serialization using mapping API.

Delucia