This post originated from an RSS feed registered with .NET Buzz
by Scott Hanselman.
Original Post: Returning DataSets from WebServices is the Spawn of Satan and Represents All That Is Truly Evil...
Feed Title: Scott Hanselman's ComputerZen.com
Feed URL: http://radio-weblogs.com/0106747/rss.xml
Feed Description: Scott Hanselman's ComputerZen.com is a .NET/WebServices/XML Weblog. I offer details of obscurities (internals of ASP.NET, WebServices, XML, etc) and best practices from real world scenarios.
(Nah, I don't really believe that, but it's a good title, no? DataSets have
there place, just not as publically visible Business Objects or from publically accessible
WebServices.)
Barry Gervin
commented on my "quick bash at DataSets" and that I didn't explain my reasonining.
In his post, Barry commented on Harry Pierson's statement
that one shouldn't use DataSets in a Web Service because they aren't compatible with
non .NET Platforms. Barry says, "This isn't true. A DataSet is just XML."
Well, of course it's XML, but if I say, hey take this sentence, it's in the ASCII
character set (who care's if it isn't English)
Le "DataSet" n'est pas votre ami si vous faites des Services
de Web. Well, Barry can understand that, but I no hablo French. ;)
DataSets are bowls, not fruit. Do you really want to return bowls?
A DataSet is an object, right? But it's not a Domain Object, it's not an "Apple"
or "Orange" - it's an object of type "DataSet." A DataSet is a
bowl (one that knows about the backing Data Store).
A DataSet is an object that knows how to HOLD Rows and Columns. It's an object
that knows a LOT about the Database. But I don't want to return bowls.
I want to return Domain Objects, like "Apples."
"Use Strongly Typed DataSets," you say. "They are the same as Objects, and look
how intellisquish works now!"
No, they still aren't Domain Objects, a Strongly Typed DataSet is just
a bowl with a picture of an Apple on it. "Look there's an
Apple INSIDE - we've broken it down into columns!" DataSets are a shoddy replacement
for a good Domain Model (and that includes Strongly Typed DataSets).
Barry has a very
good argument for the use of DataSets on his site, and I won't go through his
list agreeing and disagreeing with various points. I will say this, however,
it seems that his arguments support the use of DataSets in a Data Access Layer
- not in a Business Object Layer. THAT I would support. Additionally I
understand the usefulness of DataSets in a classic (intranet) Client-Server WinForms
app with lots of DataBinding.
Now, why shouldn't we return DataSets from WebServices? DataSets and their serialized
XML format includes a pile of information that has little to do with the Domain Model
itself. DataSets may be DiffGrams, they may or may not include schema,
and they represent "Sets of Data." They are an object of one type, DataSet.
Whether there is a Java version of a DataSet object available doesn't matter.
They are late-bound by nature, as even a Strongly Typed DataSet encapsulates conversion
of types back and forth from SqlDataTypes to typical CLR types and calls to Rows["Apple"]. DataSets
are the Class equivalent of an Variant - an Object that can be any kind of Object -
only serializable as XML. Returning an object of type DataSet
or Typed DataSet via publically accessible Web Service would succeed only in
confusing a Java person, stymying any chance of interop, and giving them more ammo
to use against .NET.
To be clear, I WOULD architect a system that included DataSets if I felt that they
provided an exceptional value. I'm just promoting that folks BE AWARE of the
ramifications of their decisions.
Tagential aside: There's some yummy best practices up on TheServerSide.NET.
Here's my favorites:
Using a DataReader vs. a DataSet: The DataReader was of course faster.
It was faster by 16% in this particular case.
SQLDataReader vs. OleDBDataReader: Going with native drivers is always
better. The SQLDataReader was 115% faster than going through OLE.
DataReader Column Reference - By Name, Ordinal, or GetString(): The
order of speed? dr[0] was the fastest, followed by dr["ProductName"], followed by
dr.GetString(0) as it has to do the conversion.
Inline (DataReader) vs. Controls (DataGrid): The inline script was
233% faster than a DataGrid component.