Search This Blog

2010-04-30

LINQ to SQL + Serialization

So here I am for my first /real/ post. I recently faced off with serializing LINQ to SQL generated types with custom properties. "I" have done this before using WebMethods by simply returning them:

1
2
3
4
5
6
7
8
9
10
11
[WebMethod]
public EntityA GetEntityA(int id)
{
    using(var db = new MyDataContext())
    {
        return db.EntityAs.SingleOrDefault(
                o => o.id == id);
    }
}
 
 
Custom properties serialize fine that way and show up on the client-side (in JavaScript). The serialization is all handled for me by ASP.NET though. The way I originally was doing serialization is like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
var sb = new StringBuilder();
var xs = new XmlSerializerFactory(
        ).CreateSerializer(
        entityToBeSerialized.GetType());
 
using(var xw = XmlWriter.Create(sb))
{
    xs.Serialize(xw, entityToBeSerialized);
}
 
var serialized = sb.ToString();
 
 

This was working sufficiently for what I was using it for because the entities had no custom properties that were required in the serialization. Now I have entities that /do/ require their custom properties to be serialized. It took a little bit of Googling to find the solution (who has time to R all TFMs?). I found a solution that works (on MSDN, no less).

http://msdn.microsoft.com/en-us/library/bb546184.aspx

In short, you enable serialization for the LINQ to SQL model by opening it (the .dbml) in Visual Studio and setting the Serialization Mode (the only options I see are None and Unidirectional; guess which one to set it to). This tells LINQ to SQL to markup the generated types with serialization attributes. Next, I needed to markup my own custom properties with these same attributes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[DataMember]
public int SomeCustomProperty
{
    get
    {
        ...
    }
 
    set
    {
        ...
    }
}
 
 

Finally, I had to change the way I was serializing (my original way isn't aware of, or at least doesn't seem to care about, the attributes we've applied).

1
2
3
4
5
6
7
8
9
10
11
12
var dcs = new DataContractSerializer(
        entityToBeSerialized.GetType());
var sb = new StringBuilder();
 
using(var xw = XmlWriter.Create(sb))
{
    dcs.WriteObject(xw, entityToBeSerialized);
}
 
var serialized = sb.ToString();
 
 

This is what is currently working for me, at least. ;) Best practices and "'Ur Doin' It Wrong, n00b!" are welcomed. :P

** EDIT **

Note that the output is slightly different from the output of the original serialization classes, so code that you've written based on the old XML structure may need to be modified. I now have to remap a set of XPath expressions... Sigh. In truth, it's resulting in slightly better code though, IMHO.

No comments:

Post a Comment