Now that we have expounded all the reasons to not use them, let's look at how to create an untyped DataSet. There are two types of untyped DataSets. The first type is the kind we have been discussing up until now, the DataSet that is configured at runtime. The other type is the kind that is configured manually, without using a DataAdapter. This kind of untyped DataSet is created using the design-time properties and methods of the DataSet itself. One of the reasons for using this type of DataSet is when you are not using data from a database. You could be creating an organized, table-style DataSet from user data entry, or you may not have connectivity to a database and you want the user to enter data to be updated to the database later.
Adding Tables at Design Time
You can add tables to the DataSet at design time using the Tables collection. This is accessible in the Property window. Note that this is only available with untyped DataSets. Before we create our untyped DataSet, let's start a new Windows Forms project and call it ADOBook07-02. Name the form frmDataSet2. Name the class and the file the same thing. Next , add a DataSet to the project by dragging one from the toolbox. Select Untyped DataSet in the DataSet wizard. Now we will set up the DataSet with an address book table.
To access the Tables collection visually, click on the ellipsis button next to its entry in the Properties window (see Figure 7.10).
Figure 7.10. The Tables collection in the Properties window.
This opens the visual collection designer. This designer is used to visually manipulate many collections in the .NET Framework, not just ADO .NET. The designer allows you to add and edit collections. Let's look at the blank Tables collection in Figure 7.11.
Figure 7.11. The collection editor.
To add a table to the collection, click the Add button. A new empty table will be added called Table1. You may change the name of the table by editing the TableName property. Let's call our table AddressBook . To add columns to the table, click the Columns collection ellipsis button in the property pane of the collection editor, as in Figure 7.12.
Figure 7.12. Accessing the Columns collection.
Let's keep our address book simple by including only the name, address, phone number, age, and birth date. Add the columns so your editor looks like Figure 7.13.
Figure 7.13. The Columns collection.
Make sure you make the Age column an int16 data type and the BirthDate column the DateTime data type. We want to do this so not all the columns are strings. This way we can see what the XML looks like for data types other than string (see Figure 7.14).
Figure 7.14. Selecting a different data type.
Now let's add our friendly grid control to the form and a panel. We'll make our form similar to the last project. Now add three buttons to the panel control. When you have finished, your form should look like Figure 7.15.
Figure 7.15. Untyped DataSet demo form.
Make sure you set the DataSource property of the grid control to DataSet1.addressbook. This way the columns of the grid will populate themselves . If you have not already dragged the OpenFileDialog and SaveFileDialog objects to the form, do so now. Now let's add the following code to the button click event procedures:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim strFile As String Try SaveFileDialog1.DefaultExt = "xml" SaveFileDialog1.Filter = "XML Files*.xmlAll Files*.*" SaveFileDialog1.ShowDialog() strFile = SaveFileDialog1.FileName If strFile = "" Then Exit Sub DataSet1.WriteXml(strFile) Catch errobj As Exception MsgBox(errobj.Message) End Try End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Dim strFile As String Try OpenFileDialog1.ShowDialog() strFile = OpenFileDialog1.FileName If strFile = "" Then Exit Sub DataSet1.ReadXml(strFile) DataSet1.AcceptChanges() Catch errobj As Exception MsgBox(errobj.Message) End Try End Sub Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click Dim strFile As String Try SaveFileDialog1.DefaultExt = "xsd" SaveFileDialog1.Filter = "XSD Files*.xsdAll Files*.*" SaveFileDialog1.ShowDialog() strFile = SaveFileDialog1.FileName If strFile = "" Then Exit Sub DataSet1.WriteXmlSchema(strFile) Catch errobj As Exception MsgBox(errobj.Message) End Try End Sub
Notice that we've added some code to save the XML schema to a file as well. We will see what this will be used for a little later on. Right now, let's run the program. Type some data into one or two rows of the grid control. Now click the Save XML button. A File Save dialog should open. Type in a file name and click OK. Now let's go to Windows Explorer and open the file. If you double-click the file, it should open in Internet Explorer, but you can open it in Notepad as well. You can see the file is XML text:
<?xml version="1.0" standalone="yes"?> <DSAddr> <AddressBook> <Last_x0020_Name>Howell</Last_x0020_Name> <First_x0020_Name>Bob</First_x0020_Name> <Address>3 Robin Lane</Address> <City>Farmingdale</City> <State>NY</State> <ZipCode>11735</ZipCode> <Phone>555-1212</Phone> <Age>49</Age> <BirthDate>1952-11-12T00:00:00.0000000-05:00</BirthDate> </AddressBook> </DSAddr>
Notice that there is no indication of the data type of the column in the file. Also notice the interesting way it saves the Birth Date column, paying particular attention to the last characters after the minus sign. This represents the time zone. All you have to do to convert to Universal Time Coordinate (UTC) is parse the time zone out and then do a dateadd function on it, reversing the sign. Then from UTC you can convert it to any local time zone you want as long as you know the offset from UTC.
This still does nothing to support the data types of the original columns. The only thing that would happen if you tried to load an alpha into a numeric column is a type mismatch error. If we loaded our XML file into a blank DataSet, it would create all string columns. So how do we save the schema data so we can ensure that our DataSet has the correct column definitions? Use a typed DataSet. We mentioned at the beginning of the chapter that there is a command-line tool that can be used to generate a class module from an XSD file. We know we have a way to save the schema to an XSD file. Once we have the XSD file we can then use the tool to create a class module. We can then import the class into our project and use it to create a typed DataSet.
To create the XSD file, run the project and click the Save Schema button. When prompted, enter a file name. Now close the program. Start a command prompt and navigate to the directory where your XSD file is located. To generate the VB DataSet, use the following command line:
C:\Documents and Settings\bhowell\My Documents\Visual Studio Projects\ADOBook\AD OBook07-02\bin>xsd AddrBook.xsd /d /l:vb Microsoft (R) Xml Schemas/DataTypes support utility [Microsoft (R) .NET Framework, Version 1.0.3705.0] Copyright (C) Microsoft Corporation 1998-2001. All rights reserved. Writing file 'C:\Documents and Settings\bhowell\My Documents\Visual Studio Proje cts\ADOBook\ADOBook07-02\bin\AddrBook.vb'. C:\Documents and Settings\bhowell\My Documents\Visual Studio Projects\ADOBook\AD OBook07-02\bin>
There are several options for this utility. The /d tells it to generate a DataSet. The other option, /c, tells it to generate a class file. The class file is not a DataSet, it is a generic class file that you can use in lieu of a DataSet if you do not need the features of one. The /l:vb switch tells it to generate Visual Basic code. The default is C#. You cannot generate C++ code at this time.
Once you have your DataSet class generated, you can include it in your project. Once you have done so, before you do anything else, you must compile the project. This is so the data type of the new DataSet class gets included in the compiled project and you can create instances of it. Then delete the existing DataSet. Now drag a new DataSet from the toolbox. When you drop the DataSet, the wizard will open. Select Typed DataSet and use the default entry, which should be the DataSet class we just created. It will create a DataSet called AddrBook1. Now you must reset the DataSource property of the data grid to this new DataSet. Once you have done all of this, you can test the program by loading the existing XML data back into the program. If all went well, the data should appear back in the grid.