Scott Hansleman has been talking about multi-tiered architecture and his latest almost gibes with my view: DataSets have their place, but not as a business object, (especially if you are going to return them from a web service). [Also see Barry Gervin's post Datasets vs. Custom Entities]
Scott had previously posted a good explanation of multi-tiered design.
Here’s a good snippet on the business layer:
Things your BizLogic Layer shouldn't know about: Ideally your business logic layer shouldn't know there is a database. It shouldn't know about connection strings or SQL. It shouldn't know about much of anything except whatever format you choose to represent your objects in (preferably NOT DataSets.)
But, at the end of Scott’s post on DataSets, he points to TheServerSide.Net’s best practices, which are very old school, and are about to be phased out of existence. The one major problem I have with the best practices is that they say DataReaders are better than DataSets. DataReaders break the rules on multi-tier design (because you can’t close a connection until you are done with a DataReader, you are now forcing Data Access logic in the Business Layer).
But, you still need some sort of data transport object to expose your data to the business layer. XmlReader is a very good one, especially if you added XmlSerialization to your BizObjects. If you are using SQLXML (specifically the For XML clause in SQL Server), XmlReader may even make even more sense, except for the fact that the Sq1Command.ExecuteXmlReader would have to be read into a local memory stream and then pass up the XmlReader for the memory stream (in order to close the connection) to the business layer (basically creating a local cache). Well, that kind of sucks, and it is only the best option if you are using XmlSerialization (and if there was no business logic involved with the transformation from XML to object, why even de-serialize it. Just spit it out of the web service, raw).
So if XmlReader isn’t the (usual) correct answer, what is? XPathNavigator BABY! Why, because it can be used to navigate over many different data stores, not just XML. And with it, comes the power (and the ability to compile and cache queries) of XPath. Just load a XPathDocument (which is optimized for XPath queries over XML) using the same XmlReader returned from the SqlCommand.ExecuteXmlReader(), and then generate a navigator from the root, XPathDocument.CreateNavigator(), and pass that up to the business layer. From there, the business layer can create, compiled, and cache XPathExpressions to transform the XML to business objects. For each business object, create a constructor that accepts a cloned XPathNavigator. And as a side benefit, XPathDocuments are read only (for now), so you can be sure that a rogue business object doesn’t screw with the data from the DAL. And what if you aren't using a store that exposes XML (like OLEDB)? You can always drop back to a DataSet and use System.Xml.XmlDataDocument.CreateNavigator. Now, your business layer truly doesn't care about the data store. And if you are really using some obscure data store, you could always add the IXPathNavigable interface, and you are still good to go.
Oh, I’m sure you would like some working examples. Well, I’ve been working on them, since I replied to Jay Kimble’s post on DataSets. I’m almost done, and should have a C# version up within a day or two, utilizing DAAB 3.1 RC1.