Geeks With Blogs

Frank Wang's inspirations on .NET
IEnumerable<Inspiration> inspirations = from i in DataContext.Inspirations where i.Sharable == true select i

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.

image

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.

DBML

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.

image

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.

image

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.

image

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.

Posted on Friday, August 29, 2008 7:14 PM LINQ | Back to top


Comments on this post: Serialization issue with timestamp in LINQ to SQL

# re: Serialization issue with timestamp in LINQ to SQL
Requesting Gravatar...
Frank,

The problem with this approach is that it doesn't work if you want to use the Table<T>.Attach(modified, original) overload, such as when you are using a disconnected data context.

The issue is that deep in the bowels of Linq when calling .SubmitChanges() it does a .Equals comparison on each of the persisted fields, which fails for byte[]. This results in an "A member that is computed or generated by the database cannot be changed" error.

You may be aware of this but others thinking this is the nirvana solution and finding this entry may not be.

What is the "ultimate solution" to both problems? Still looking - but I think what Andrew Siemer proposes in terms of using a string is likely a better bet.

http://geekswithblogs.net/frankw/archive/2008/08/29/serialization-issue-with-timestamp-in-linq-to-sql.aspx

If however you are using the .Attach(modified, true) overload then byte[] will work for you. However that has other problems (such as non-optimised UPDATE statements).
Left by kiwidude on Oct 28, 2008 10:32 AM

# re: Serialization issue with timestamp in LINQ to SQL
Requesting Gravatar...
You will not have serialization issues in WCF, which uses DataContractSerializer. With it, System.Data.Linq.Binary is serializable - check that.
Left by Georgi Ganchev on Nov 08, 2008 3:28 PM

# re: Serialization issue with timestamp in LINQ to SQL
Requesting Gravatar...
Comment above references the wrong url for Andrew Siemer's post:
http://geekswithblogs.net/AndrewSiemer/archive/2008/02/11/converting-a-system.data.linq.binary-or-timestamp-to-a-string-and-back.aspx
Left by Joshka on Feb 17, 2009 4:54 PM

# re: Serialization issue with timestamp in LINQ to SQL
Requesting Gravatar...
thanks for your post!!
Left by carlos on Apr 22, 2009 11:04 AM

# re: Serialization issue with timestamp in LINQ to SQL
Requesting Gravatar...
Thanks for your very helpful article.

Such a simple solution to change hte Binary type to byte[] and this has saved me so much time and effort when i was almost thinking of giving up!
Left by Jo on Jul 14, 2010 6:00 AM

# re: Serialization issue with timestamp in LINQ to SQL
Requesting Gravatar...
Thank you very much. This helped me.
Left by Tushar on Dec 04, 2010 9:15 PM

# re: Serialization issue with timestamp in LINQ to SQL
Requesting Gravatar...
Simple and superb solution..........
Left by Ajay on Jul 02, 2012 11:51 PM

Your comment:
 (will show your gravatar)


Copyright © Frank Wang | Powered by: GeeksWithBlogs.net