Monday, 23 November 2009

System.Data Serialisation Bug - Scenario 1

Introduction

System.Data contains a bug which can cause it to throw an exception during serlisation or deserialisation of a DataSet which contains a column that uses System.Object as its .NET type.

The bug manifests itself in two known scenarios:

  • Serialising a DataSet containing a column of type System.Object using a System.Xml.XmlTextWriter instance created via the static Create method; this throws a System.ArgumentException.
  • Deserialising a DataSet containing a column of type System.Object after having successfully passed it across the wire via Windows Communication Foundation (WCF) using netTcp binding; this throws a System.Data.DataException.

I reported the bug to Microsoft back in 2007 whilst using .NET 2.0 and 3.0. At the time was told "it's definitely in our system for a Post Orcas release". The bug still exists in .NET Framework 3.5 SP1, although I haven't checked any of the .NET 4.0 betas yet.

This post covers the first scenario you might come across – simply serialising the DataSet with an XmlTextWriter. I'll do a follow-up next week covering the second scenario.

Reproducing the Bug

To demonstrate this behaviour we're going to need a DataSet with a System.Object column, and we're going to need to populate it with some data.

static System.Data.DataSet CreateAndPopulateDataSet()
{
  // create a DataSet containing two columns: a string (Key) and an object (Value)
  System.Data.DataSet dataSet = new System.Data.DataSet();
  System.Data.DataTable dataTable = dataSet.Tables.Add();
  dataTable.Columns.Add("Key", typeof(string));
  dataTable.Columns.Add("Value", typeof(object));

  // add two rows, one containing an integer Value, and one containing a string Value
  dataTable.LoadDataRow(new object[] { "foo", 42 }, true);
  dataTable.LoadDataRow(new object[] { "bar", "Hello World" }, true);

  // return the DataSet
  return dataSet;
}

Wednesday, 18 November 2009

Cloning Messages in BizTalk Server when CanSeek is False

Introduction

When writing custom pipeline components for BizTalk Server 2006 there are times when you want to access a copy of a message, rather than the actual message being processed. Typically this is because the original data stream containing the message is not seekable, meaning that by reading the stream you prevent the next component within the pipeline from doing so.

The BizTalk Server 2006 documentation reports that the Data method of the Microsoft.BizTalk.Message.Interop.IBaseMessagePart interface provides such a facility. According to the documentation:

"In custom pipeline components, Data clones an inbound data stream, whereas GetOriginalDataStream returns the original inbound stream."

The testing I've done, however, shows that this is only the case if the original data stream is itself seekable. It seems likely that this is because a stream must be read in order to be cloned, and if it is not seekable it could never be returned to its original position following the clone. So BizTalk Server cannot honour the request to clone the stream if the stream is not seekable.

This article describes a utility method, GetSafeDataStream, which retrieves a stream which can be safely read without adversely affecting the original data stream.

Caveat: The information in this article applies to BizTalk Server 2006. Your mileage with other versions may vary.

Monday, 16 November 2009

Welcome

Conventional wisdom suggests that the first post of any new blog (such as this one) should be in the form of an introduction. I'm sure you don't really care if I'm married (I am) or if I own a cat (I don't) so I'll dispense with an introduction of myself and plough on with an introduction of the blog itself. (If you really want to know something about me, you can view my profile on LinkedIn.)

There are several reasons why I've never blogged before. The primary reason is that I don't really have as much free time as many bloggers seem to have, so I can't really see myself keeping up the steady flow of posts which might be expected. Also, as my knowledge-base is quite varied I've always found it difficult to target the blog at any specific topic - I might have something worth saying on ASP.NET one minute and BizTalk Server the next. There are, however, several occasions where I've discovered some non-obvious piece of information and have felt the desire to share it with the world - but have not had a medium by which to do that. Another such occasion arose recently so I decided to take the plunge and set-up a blog.

By way of a theme, I realised that many of the topics which I'd like to discuss are about the internal mechanics of some piece of software or other: the sort of thing that isn't fully documented (if it's documented at all) and which can only be discovered by trial and error or (preferably) by firing up Lutz Roeder's .NET Reflector. I've therefore decided to name the blog Under the Covers.

I've got topics lined-up on the unusual behaviour of the Data property of BizTalk's IBaseMessagePart class, a bug in System.Data.DataSet.WriteXml and how to 'undrop' a table in SQL Server 2005.