Now let's look at the DataSet class. As we've said, the DataSet class is primarily used to read store and write XML data. It cannot access the database directly. In the previous chapter we examined the DataAdapter and showed how it is used to feed data into the DataSet. We did this from the perspective of the DataAdapter. Now we will do it from the perspective of the DataSet.
We said earlier that you do not have to know anything about XML to use the DataSet, but it does help. If we do nothing more than use the DataSet programmatically as an in-memory data cache for database tables we'll never have to touch XML again. But this is only part of the power of the DataSet. If we want to use the full power of the DataSet we must also learn how to read and write XML directly without using a database. The beauty of this is that even to do this you really do not need to know all the XML tags and details.
The DataSet class is primarily a collection of DataTable objects. It also contains a Relations collection. The DataTable objects contain the definition of the data and the data itself. The DataTable is similar to a table in SQL Server database. It contains rows, columns, and constraints. Instead of using native database data types for the columns , it uses the standardized XSD document data types defined by Microsoft. This way we do not have to be concerned about whether we are using Oracle, SQL Server, Access, or some other database. Once the data is stored in the DataSet all of the data types are standardized. This makes writing one single code base for many different database back ends much easier. All you need is a different interface layer for each database feeding a common DataSet.
As we said the DataTable is a collection of rows and columns similar to a database table. The DataTable itself is a collection of collections. There is a Rows collection and the Columns collection. The Columns collection corresponds to the XSD document and contains metadata describing the table. The Rows collection corresponds to the XML document and contains the actual data. But take a look at how the DataTable is represented visually by the XML editor (Figure 7.1).
Figure 7.1. The XML editor showing the DataTable.
Figure 7.2 shows how this same data looks when viewed through the DataSet Properties page.
Figure 7.2. The DataTable viewed via the Properties page.
The Properties page displays the same view of the data without the XML context. You can edit the data only through the XML view because this is a typed DataSet. If it weren't, you could edit the metadata through the Properties page as well. We will explain the difference between a typed and untyped DataSet a little later. Right now we're dealing with a typed DataSet. The short explanation is that the DataSet was subclassed when we declared it through the wizard. This will be covered in detail later in the chapter.
To begin our demonstration let's create a new Windows Form project. Name it ADOBook07-01. Drag and drop the DataAdapter onto the form. When the wizard starts, select the Northwind database. In the SQL Builder select the Customers table. You know how this works, so finish the builder. Next, right-click on the DataAdapter and select Generate DataSet. You should see the dialog box in Figure 7.3.
Figure 7.3. The Generate DataSet dialog.
Clicking the OK button generates a typed DataSet with the Customers table already created. It will also add the DataSet to the designer. That's about as easy as it gets with DataSets. What this did was use the information in the DataAdapter to create an inherited class named DataSet1. Then the wizard created an instance of a DataSet class called DataSet11 of type DataSet1. I know it sounds confusing but I will clear it up later. You can use this wizard over and over to make changes to existing DataSets by adding new tables from new DataAdapters.