Linq to Sql, by default, does not enable serialization. This is no problem when dealing with business objects directly, but what if you throw in Windows Communication Foundation? Or, maybe you have some business requirement mandating the use of Xml files. Luckily, LINQ makes dealing with both of these potential problems quick and painless. This first article shows you how to enable unidirectional serialization, explains how it works, and discusses drawbacks for this approach.
Enabling Xml Serialization in Linq to Sql
First you have to enable Xml Serialization on your LINQ objects.
In Visual Studio, open your DBML file in the ORM Designer. Open the properties pane on the right to see your DBML Data Context Properties. If you don’t see the same properties list shown in the image above, click anywhere in the ORM Designer’s whitespace to ensure you haven’t selected a table or something.
Then, select the drop down list for Serialization Mode and select Unidirectional.
Your LINQ objects now support unidirectional serialization.
How Unidirectional Serialization Works
How it works is actually much more long winded than how to get it done, but it is important to know what wizardry the ORM designer is doing for you, and helps me explain a few things later. This article uses a (very) simple blogging database consisting of three tables:
The following is the signature of our Blog table, as defined in the designer code behind of the generated DBML file Linq uses:
[Table(Name="dbo.Blog")]
public partial class Blog : INotifyPropertyChanging,
INotifyPropertyChanged
{
Here is the same signature, after serialization has been enabled:
[Table(Name="dbo.Blog")]
[DataContract()]
public partial class Blog : INotifyPropertyChanging,
INotifyPropertyChanged
{
Note the addition of an attribute, DataContract. This labels the class as Serializable. Most of the object’s properties have a similar addition. Here is the Blog’s title, before:
[Column(Storage="_Title", DbType="NVarChar(50)
NOT NULL", CanBeNull=false)]
public string Title
{
And after:
[Column(Storage="_Title", DbType="NVarChar(50)
NOT NULL", CanBeNull=false)]
[DataMember(Order=3)]
public string Title
{
Note the DataMember attribute. The Order parameter it takes in reflects the order of the columns in the database, and ensures that during serialization the properties will always end up in the same order they were in before.
Limitations of Unidirectional Serialization
Now, there are limitations to this solution. Serialization done here is unidirectional; it only goes one way. You cannot (easily) convert a serialized LINQ object back to its former self without losing some references. In other words, your objects won’t be able to make a round trip, so this solution will not work for services that require this.
In fact, cycles are the main reason why this problem exists. If you look closely at the generated DBML again, you might notice that some properties are not marked with the DataMember attribute. To avoid a cyclical dependency issue in Xml serialization, LINQ will not label child to parent relationship properties as serializable. For example, the User object contains an EntitySet of Blogs, which is marked for serialization:
[Association(Name="User_Blog", Storage="_Blogs", OtherKey="UserId")]
[DataMember(Order=5, EmitDefaultValue=false)]
public EntitySet<Blog>
Blogs
{
However, on the Blog object, its reference to the user does not:
[Association(Name="User_Blog", Storage="_User", ThisKey="UserId", IsForeignKey=true)]
public User User
{
So, when you serialize the Blog object, it won’t have any mention of a relation to the User. The User object will have a list of related blogs, so you can maintain the relationship, but this problem cripples having bidirectional serialization without also forcing introduction of some serious processing overhead (which, in addition to the cyclical headache, is probably why it is not supported in .NET 3.5).
Conclusion
Unidirectional serialization has its problems, but can still prove quite useful. In my next article I will discuss a few ways to take advantage of serializable Linq objects using some helper classes Microsoft stuffed in the dark corners of System.Runtime.Serialization, and maybe I’ll throw in some LINQ to XML while I’m at it. Stay tuned.
Read and post comments |
Send to a friend