Friday, March 5, 2010

DataSets Considered Harmful (part 2): Performance

@YaronNaveh

The first part in this series discussed various interoperability issues with DataSets. This time I want to discuss the performance implications.

Let us sent the simplest DataSet to some server:

var ds = new System.Data.DataSet();
DataTable t = new DataTable();
t.Columns.Add("col1");
t.Columns.Add("col2");
t.Rows.Add("row1col1", "row1col1");
t.Rows.Add("row2col1", "row2col1");
ds.Tables.Add(t);
localhost.Service s = new Service();
s.GetData(ds);

Here is the generated Soap:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body>
        <GetData xmlns="http://tempuri.org/">
            <value>
                <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
                    <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
                        <xs:complexType>
                            <xs:choice minOccurs="0" maxOccurs="unbounded">
                                <xs:element name="Table1">
                                    <xs:complexType>
                                        <xs:sequence>
                                            <xs:element name="col1" type="xs:string" minOccurs="0" />
                                            <xs:element name="col2" type="xs:string" minOccurs="0" />
                                        </xs:sequence>
                                    </xs:complexType>
                                </xs:element>
                            </xs:choice>
                        </xs:complexType>
                    </xs:element>
                </xs:schema>
                <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
                    <NewDataSet xmlns="">
                        <Table1 diffgr:id="Table11" msdata:rowOrder="0" diffgr:hasChanges="inserted">
                            <col1>row1col1</col1>
                            <col2>row1col1</col2>
                        </Table1>
                        <Table1 diffgr:id="Table12" msdata:rowOrder="1" diffgr:hasChanges="inserted">
                            <col1>row2col1</col1>
                            <col2>row2col1</col2>
                        </Table1>
                    </NewDataSet>
                </diffgr:diffgram>
            </value>
        </GetData>
    </soap:Body>
</soap:Envelope>

This Soap commits two “crimes”. The first one is the embedded schema. Since the wsdl is not typed, .Net must serialize the schema inside the soap. This can have serios performance implications with large schemas.

The second issue is the rowOrder and hasChanges attributes over each data row. In most cases when you just want to pass a snapshot of data to a client so these are simply not required.

The overall result is a bloated Soap without any meaningful benefit.

@YaronNaveh

What's next? get this blog rss updates or register for mail updates!

1 comments:

Moshe said...

Hi Yaron. I very liked your 2 latest posts about the penalties of using DataSet in the web service contracts.