Friday, August 29, 2008 7:14 PM
Many of you use timestamp in LINQ to SQL because it's easier for us figure out if an object is new or not. This is specially useful when we need to track the state of objects in disconnected/N-tier scenarios. An important thing to note, though, is that the timestamp column is mapped as a System.Data.Linq.Binary property in the LINQ generated object so it is part of the XML serialization when you use the LINQ to SQL objects in Web Services/WCF services. The real problem is that System.Data.Linq.Binary doesn't have a parameterless constructor. Take a look at the Binary's constructor documented in MSDN. There's no parameterless constructor available to the class. What this means is the serialization of timestamp will fail for sure when you pass the object around in your service calls.
C#
public Binary(
byte[] value
)
To prove my point, we can create a Web Service that returns a LINQ to SQL object with the timestamp field. First of all, let's add a timestamp column to the Products table in Northwind.
Save the table. Create a new Web Service project named NorthwindProductService. Add a LINQ to SQL file Northwind.dbml into the project. We only need the Products table in the dbml file for our sample to work.
Find the definition of the TimeStamp property in the LINQ generated class. You will see the type of this property is System.Data.Linq.Binary.
[Column(Storage="_TimeStamp", AutoSync=AutoSync.Always, DbType="rowversion NOT NULL", CanBeNull=false, IsDbGenerated=true, IsVersion=true, UpdateCheck=UpdateCheck.Never)]
public System.Data.Linq.Binary TimeStamp
{
get
{
return this._TimeStamp;
}
set
{
if ((this._TimeStamp != value))
{
this.OnTimeStampChanging(value);
this.SendPropertyChanging();
this._TimeStamp = value;
this.SendPropertyChanged("TimeStamp");
this.OnTimeStampChanged();
}
}
}
At last, let's add a simple web method called GetProductByID that returns a Product object from the LINQ to SQL data context.
[WebMethod]
public Product GetProductByID(int productID)
{
return new NorthwindDataContext().Products.Where(p => p.ProductID == productID).SingleOrDefault();
}
Now run the Web Service from Visual Studio. The asmx file throws the serialization exception immediately. We haven't even got a chance to invoke the GetProductByID method. But the exception does make all the sense as an object without parameterless constructor cannot be serialized.

Don't be desperate yet. Every problem has a solution :-) LINQ to SQL has provided a way to change the data type of every property that is mapped to the actual table column. By default, LINQ uses the original type of the column. As you can see in the LINQ designer surface, the data type of TimeStamp is automatically set to System.Data.Linq.Binary.
All you have to do is change the data type from System.Data.Linq.Binary to byte[], which doesn't need to be instantiated during the serialization.
Compile and run the Web Service again. It's no longer complaining about the serialization issue. The source code for the sample we did in this blog post can be downloaded from my Live SkyDrive.