Tips: Using Strong Typed DataSets with Web Services

Before I start this article, let me be up front and state that I do not use DataSets 100% of the time.  I do use the heck out of them in demos and presentations because, well, they demo well.  There is a never ending debate on whether to use DataSets or not.  I say use them, but not in all situations.  That's my official stance on them.  In a lot of cases they make sense, espeically when doing binding to a DataGrid and reconciling changes, in others they don't.  We are not here today to argue for or against them though.  What I will share with you are some tips that many may or may not know when using DataSets with Web Services.   

Tip #1:  Include Only What You Need

As the tip states, include only the tables you need.   I never create one master DataSet with all of my tables from my Database.  I find it to be hard to work with and typically if I am working on a module basis which means I don't need everything anyway, just the tables that apply to the module I am working with.  I see a lot of time where people create DataSets where they include the entire database in a DataSet.  I don't, especially for modules.  A lot of the time I will have a DataLayer that is made up of several different DataSets, not one large one.  Here's an example of what I'm talking about:

 

This example from the AdventureWorks database has only two DataTables in it:  Contact and ContactType.  This is all I need if I am going to deal with a Contact.  It is easier to manage and look at, and less of a code footprint.   If you are passing this information over a web service, by default, the schema of the DataSet goes along for the ride.  Having more tables, means more schema information, which brings me to my second tip.

Tip #2:  Don't Include Schema Information

If you are using a Strong Typed DataSet, before you return your DataSet from a Web Service, mark it to not include the schema.  Here is a sample web method using the Strong Typed DataSet seen above.

       [WebMethod]

        public ContactDataSet GetContactsByLastname(string lastname)

        {

            DataLayer.ContactDataSetTableAdapters.ContactTableAdapter ta = new DataLayer.ContactDataSetTableAdapters.ContactTableAdapter();

            ContactDataSet ds = new ContactDataSet();

            ds.Merge(ta.GetByLastName(lastname));

            return ds;

        }

 Here is the output from this web method saved to the file system. 

The majority (95%) of what is in the file is the Schema Definition for the DataSet.  This is why the file is 5.23KB.  The only part we *really* want is the row data.  This is one of the major reasons people stay away from DataSets.  Which is a shame since they provide a lot of functionality.  It turns out we can fix this problem with one line of code.  Here is the new code sample whereby we exclude the schema:

        [WebMethod]

        public ContactDataSet GetContactsByLastname(string lastname)

        {

            DataLayer.ContactDataSetTableAdapters.ContactTableAdapter ta = new DataLayer.ContactDataSetTableAdapters.ContactTableAdapter();

            ContactDataSet ds = new ContactDataSet();

            ds.Merge(ta.GetByLastName(lastname));

            ds.SchemaSerializationMode = SchemaSerializationMode.ExcludeSchema;

            return ds;

        }

 If we run this example which excludes the XSD, we immediately see a smaller footprint.  We go down from 5.23KB to 1.54KB:

And here is the output from the web service.  Much much smaller than previous, and it contains the data we primarily care about althought it does include a few straglers which I would like to see removed entirely from future versions.  Maybe the .Net team can add a new flag to the enumeration which is SechamSerializationMode.JustGiveMeMyData. :)

<?xml version="1.0" encoding="utf-8"?>

<ContactDataSet msdata:SchemaSerializationMode="ExcludeSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns="http://keithelder.net/">

    <xs:schema id="ContactDataSet" targetNamespace="http://tempuri.org/ContactDataSet.xsd" xmlns:mstns="http://tempuri.org/ContactDataSet.xsd" xmlns="http://tempuri.org/ContactDataSet.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" attributeFormDefault="qualified" elementFormDefault="qualified">

        <xs:element name="ContactDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">

            <xs:complexType>

                <xs:choice minOccurs="0" maxOccurs="unbounded" />

            </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">

        <ContactDataSet xmlns="http://tempuri.org/ContactDataSet.xsd">

            <Contact diffgr:id="Contact1" msdata:rowOrder="0">

                <ContactID>19978</ContactID>

                <NameStyle>false</NameStyle>

                <FirstName>Keith</FirstName>

                <LastName>Elder</LastName>

                <EmailAddress>not@telling.com</EmailAddress>

                <EmailPromotion>1</EmailPromotion>

                <PasswordHash>hash</PasswordHash>

                <PasswordSalt>salt</PasswordSalt>

                <rowguid>cd9ea7c0-d192-4a9f-9999-e9a0c6b117a9</rowguid>

                <ModifiedDate>2007-01-30T11:16:48.703-06:00</ModifiedDate>

            </Contact>

        </ContactDataSet>

    </diffgr:diffgram>

</ContactDataSet>

Note, if you are using plain datasets, you have to include the schema, always.

 Tip #3:  Enable GZIP on IIS

The last tip while not exclusive to DataSets is worthy of noting nontheless.  That is to turn on Gzip compression in IIS.   You will notice a drastic performance increase of data moving over the wire.  XML compresses really well with Gzip and I've seen 20K or 26K messages get turned in 2-4K easily.  For smaller messages you may don't want to Gzip since it will actually add to the message footprint.  The good news is when you create your proxy class to call the web service, you can choose if you want to support it or not.  Here's an example:

 

MyService proxy = new MyService();
proxy.EnableDecompression = true;

This is supported in .Net 2.0.  The above lines will set the HTTP header when the service is called to tell IIS that Gzip compression is supported and IIS will then zip the contents and send them back down.  If you have a very small message then set this to false, otherwise you will add overhead of the compression. 

Technorati tags: , , , , ,

Like This Article?  kick it on DotNetKicks.com

posted @ Friday, February 23, 2007 12:06 PM

Print

Comments on this entry:

# Tips: Using Strong Typed DataSets with Web Services

Left by DotNetKicks.com at 2/23/2007 12:11 PM

You've been kicked (a good thing) - Trackback from DotNetKicks.com

# re: Tips: Using Strong Typed DataSets with Web Services

Left by Steve at 2/25/2007 3:58 PM
Gravatar

Just a quick heads up - you seem to have gotten your images of the xml file outputs mixed up. No big deal but you may want to switch them around the right way.

Cheers.

# re: Tips: Using Strong Typed DataSets with Web Services

Left by James Hancock at 2/26/2007 10:55 PM

As I have found out the hard way, using DataSets while great, also has serious problems. No matter how you go about it, there is a hard limit of about 30 megs of data. This isn't because of DataSets, it's because of the System.Text.StringBuilder and also encryption level events that happen while serializing the data (especially with WSE). Even if you allow huge uploads and downloads, it will still crash with an out of memory exception.

So if you know that you'll never send more than 30 megs at a time, great. But if you're not sure, get ready to chunk your data... it's ugly, but there isn't any other way around it currently because of the bugs in StringBuilder and the encryption classes.

(BTW, this comment entry form is completely screwed in IE 7 on Vista...)

# re: Tips: Using Strong Typed DataSets with Web Services

Left by Keith Elder at 2/27/2007 9:12 AM
Gravatar

Actually the images aren't messed up, but the point isn't coming across clearly. I'm going to remove it for clarity. Thanks.

# re: Tips: Using Strong Typed DataSets with Web Services

Left by Keith Elder at 2/27/2007 10:05 AM
Gravatar

The only time I've ever gotten the Out of Memory exception was when in fact I was returning a million records from a web service (I was testing, no flames please). The data came down the wire just fine but when it got to the client, it physically ran the client out of memory. Obviously this was way more than 30MBs but I wasn't using WSE with the call.

 re: Tips: Using Strong Typed DataSets with Web Services

Left by Joe B at 3/1/2007 8:01 PM

Good stuff with the ExcludeSchema and the compression.

# re: Tips: Using Strong Typed DataSets with Web Services

Left by Naveen at 7/29/2008 1:05 AM
Gravatar

This article is good.The data given was excellent.That can easily understand by the user.

Your comment:






 
 
 
Please add 2 and 5 and type the answer here:
 

Live Comment Preview:

 
«September»
SunMonTueWedThuFriSat
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011