Visual Studio 2005 Walkthrough:
ASP.NET 2.0 Web Services and ADO.NET 2.0
Article by Wim Uyttersprot (wim@u2u.be)
U2U - Brussels (www.u2u.net)
Applies to
- Visual Studio 2005 Beta
- C# 2.0.Beta
- VB.NET 2.0.Beta
Summary In
this walkthrough you will how to create an ASP.NET 2.0 Web Services that
returns and updates an ADO.NET 2.0 DataSet. The dataset is consumed in Windows
Form and bound to a DataGridView instance, using the new asynchronous patterns
of .NET 2.0. The dataset is serialized in XML. Using a XSD schema, a typed
dataset is created.
Creating the web service project
After starting Visual Studio 2005, we
create a new blank solution “NWSolution”; in our example we stored the solution
in the folder c:\U2UTutor\ADO.NET 2.0\Northwind

To the blank solution we add a “New Web
Site”:

We choose for the installed template
“ASP.NET Web Service” and give it the name NWWebSite. Giving it a name
referring to a web service would conflict with the entity that is truly
created, this is a web site.

To the NWWebSite project that is added our
solution, we add now a new web service. Therefore we use the “Web Service”
template and we name the item “NWWebService.asmx”. The programming language we
chose in our example for the coding of the web service is VB.NET.

As result a NWWebService.asmx file is added
to our project together with a “separate” file “NWWebservice.vb” containing the
application code. In our example we also removed the default created web
service file.

Opening the NWWebservice.vb code file,
shows us the web service NWWebService to be a class inheriting from the
System.Web.Services.WebService class. We change the namespace of our web
service into http://u2u.net/webservices/
and add an “Option Strict On” to work strictly typed.
Option Strict On
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
<WebService(Namespace:="http://u2u.net/webservices/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)>
_
Public Class NWWebService
Inherits System.Web.Services.WebService
Public Sub NWWebService()
End Sub
End Class
Adding the web method GetProducts
We will now add a web method “GetProducts”
that should return a dataset filled with one data table with Product records.
As the DataSet type is defined in the System.Data namespace we import it:
Imports System.Data
We use the WebMethod attribute to define
the function:
<WebMethod()> _
Public Function GetProducts() As DataSet
End Function
First we create an empty DataSet object,
give it the name “NorthwindDataSet”, refer to it with the dataset reference
that is used to define the dataset as return object of the function.
<WebMethod()> _
Public Function GetProducts() As DataSet
Dim
dataset As New DataSet("NorthwindDataSet")
Return dataset
End Function
The dataset is nothing more as a data
carrier box, and we will now fill this box with one single table. Therefore we
use a data adapter object. As we target SQL Server 2005 we will work with the
data adapter type SqlDataAdapter of the Data.SqlClient namespace and therefore
we import this namespace:
Imports System.Data.SqlClient
We create a data adapter object and request
it to Fill the dataset with a table. In the example we call the table in the
dataset “My Products” as we want to hightlight the fact that the table added to
the dataset is different from the original table in the database; so they can
have different names.
Dim
adapter As New
SqlDataAdapter
adapter.Fill(dataset, "My
Products")
An adapter object has four important
members, the SelectCommand member, the UpdateCommand, the DeleteCommand, the
InsertCommand member. For retrieving records we only need the SelectCommand.
Dim
command As New
SqlCommand
This SqlCommand object want us to define
two important properties: the command text and the connection that will be used
to invoke the command.
command.CommandText = cmdText
command.Connection = connection
The cmdText object is defined in our
example as a constant:
Private Const cmdText As String = "Select * from Products"
The connection is created as object:
Dim
connection As New
SqlConnection(connectionString)
Where the connection object is using the
constant connectionString:
Private Const connectionString As String = "Data Source=U2U-WIM2;Initial Catalog=Northwind;Persist
Security Info=True;User ID=sa;password=u2u"
It is quite trivial to understand that user
ids and passwords should better not be defined in code in connection strings;
but as this is a tutor, we expect the reader to forgive us. Students not working
on a U2U PC should of course adapt the above connection string to get this
example working on their personal machines.
One last step is to open the connection
before filling the dataset, and closing it immediately after the Fill
operation:
connection.Open()
adapter.Fill(dataset, "My
Products")
connection.Close()
The complete web service shoul look similar
to:
Option Strict On
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.Data
Imports System.Data.SqlClient
<WebService(Namespace:="http://u2u.net/webservices/")>
_
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)>
_
Public Class NWWebService
Inherits System.Web.Services.WebService
Public Sub NWWebService()
End Sub
Private Const cmdText As String = "Select * from Products"
Private Const connectionString As String =
"Data Source=U2U-WIM2;Initial Catalog=Northwind;Persist Security
Info=True;User ID=sa;password=u2u"
<WebMethod()> _
Public Function GetProducts() As DataSet
Dim dataset As DataSet("NorthwindDataSet")
Dim adapter As New SqlDataAdapter
Dim connection As New
SqlConnection(connectionString)
Dim command As New SqlCommand
command.CommandText = cmdText
command.Connection = connection
adapter.SelectCommand = command
connection.Open()
adapter.Fill(dataset, "My Products")
connection.Close()
Return dataset
End Function
End Class

After setting the NWWebService.asmx as starting
page in the solution explorer, we start the project and obtain the NWWebService
class as it looks on the net:

When we invoke the GetProducts method in
Internet Explorer, we obtain the dataset in XML:

First part of the dataset contains the
schema revealing the field names and types:
<?xml
version="1.0" encoding="utf-8" ?>
- <DataSet xmlns="http://u2u.net/webservices/">
-<xs:schema id="NorthwindDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
- <xs:element name="NorthwindDataSet" msdata:IsDataSet="true"
msdata:UseCurrentLocale="true">
-
<xs:complexType>
-
<xs:choice minOccurs="0" maxOccurs="unbounded">
-
<xs:element name="My_x0020_Products">
-
<xs:complexType>
-
<xs:sequence>
<xs:element name="ProductID" type="xs:int" minOccurs="0" />
<xs:element name="ProductName" type="xs:string" minOccurs="0" />
<xs:element
name="SupplierID" type="xs:int" minOccurs="0" />
<xs:element
name="CategoryID" type="xs:int" minOccurs="0" />
<xs:element
name="QuantityPerUnit" type="xs:string" minOccurs="0" />
<xs:element
name="UnitPrice" type="xs:decimal" minOccurs="0"
/>
<xs:element
name="UnitsInStock" type="xs:short" minOccurs="0" />
<xs:element
name="UnitsOnOrder" type="xs:short" minOccurs="0" />
<xs:element
name="ReorderLevel" type="xs:short" minOccurs="0" />
<xs:element
name="Discontinued" type="xs:boolean" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
The second part of the XML data contains
the records. First and last record looks like:
- <diffgr:diffgram
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
- <NorthwindDataSet
xmlns="">
- <My_x0020_Products diffgr:id="My Products1"
msdata:rowOrder="0">
<ProductID>1</ProductID>
<ProductName>Chai</ProductName>
<SupplierID>1</SupplierID>
<CategoryID>1</CategoryID>
<QuantityPerUnit>10 boxes x
20 bags</QuantityPerUnit>
<UnitPrice>18.0000</UnitPrice>
<UnitsInStock>39</UnitsInStock>
<UnitsOnOrder>0</UnitsOnOrder>
<ReorderLevel>10</ReorderLevel>
<Discontinued>false</Discontinued>
</My_x0020_Products>
...
- <My_x0020_Products diffgr:id="My Products77"
msdata:rowOrder="76">
<ProductID>77</ProductID>
<ProductName>Original
Frankfurter grüne Soße</ProductName>
<SupplierID>12</SupplierID>
<CategoryID>2</CategoryID>
<QuantityPerUnit>12 boxes</QuantityPerUnit>
<UnitPrice>13.0000</UnitPrice>
<UnitsInStock>32</UnitsInStock>
<UnitsOnOrder>0</UnitsOnOrder>
<ReorderLevel>15</ReorderLevel>
<Discontinued>false</Discontinued>
</My_x0020_Products>
</NorthwindDataSet>
</diffgr:diffgram>
</DataSet>
Creating a windows client application
To our solution we add a new project:

We choose for the Windows Application
template, giving it the name “NWClient” in the location “C:\U2UTutor\ADO.NET
2.0\Northwind”. In this tutor we chose the Visual C# programming language:

The new project immediately contains a
windows form that we rename to NWClientForm and to which we add a button with
name “getButton” and text “Get”.

We also dropped a DataGridView control from
the Data section of the toolbox on the Form designer; we anchored the right and
bottom borders of the DataGridView control.

In order to access the web service, we
firstly add a web reference to the NWClient project:

In the “Add Web Reference” dialog we choose
for select our NWWebService:

As Web reference name we enter NWWebSite,
as it will become the name of the namespace in which the proxy class will be
defined:

As result the web service reference
“NWWebSite” is added to the NWClient project, containing a NWWebService.disco
file, a NWWebService.wsdl file and the Reference.cs. This last file contains
the proxy class of the web service; it is generated and updated automatically.

Time to add some code now for the Click
event handler of the Get button: first we add in the “NWClientForm.cs” file a
code reference to a web service proxy instance. The proxy type defines a
NWWebSite namespace in which the NWWebService type is defined:

This creates the web service proxy object:
private NWWebSite.NWWebService service
= new NWWebSite.NWWebService();
In the event handler we call the web method
and bind the result to the datagridview object using its DataSource and
DataMember properties. This is known as complex databinding, as the hidden
internal code is complex; complex databinding makes the work of the programmer
simple:
dataGridView1.DataSource =
service.GetProducts();
dataGridView1.DataMember = "My Products";
The complete code file of the
“NWClientForm.cs” file should look like:
using
System;
using
System.Collections.Generic;
using
System.ComponentModel;
using
System.Data;
using
System.Drawing;
using
System.Text;
using
System.Windows.Forms;
namespace NWClient
{
public partial class NWClientForm
: Form
{
public
NWClientForm()
{
InitializeComponent();
}
private
NWWebSite.NWWebService service = new NWWebSite.NWWebService();
private void getButton_Click(object
sender, EventArgs e)
{
dataGridView1.DataSource =
service.GetProducts();
dataGridView1.DataMember = "My Products";
}
}
}
The result of running the client project
and clicking the Get button, will be that the DataGridView control is filled
with the data table from the dataset that was returned by the web service:

Important to notice is that in the above
code snippet, we invoke the web service in a synchronous way. It is much more
performing to access the web service in an asynchronous way. Microsoft .NET 2.0 offers us a new simple pattern based upon event handling that is thread safe.
Firstly we should call the web service method asynchronously, using a special
“Async”-method generated in the proxy code:
service.GetProductsAsync();
Secondly we should define an event handler
that will be called when the web method returns and is responsible for updating
the form UI. Notice the special GetProductsCompletedEventArgs type:
private void GetProducts_Completed(object sender,
NWWebSite.GetProductsCompletedEventArgs e)
{
this.dataset =
e.Result;
this.dataGridView1.DataSource
= this.dataset;
this.dataGridView1.DataMember
= "My Products";
}
In order to get this method called as event
handler, we should add this handler to the “GetProductsCompleted” event (this
event is also part of the generated proxy class):
this.service.GetProductsCompleted
+= this.GetProducts_Completed;
The complete client code, that consumes the
web method in an asynchronous way, should now look like this:
using
System;
using
System.Collections.Generic;
using
System.ComponentModel;
using
System.Data;
using
System.Drawing;
using
System.Text;
using
System.Windows.Forms;
namespace NWClient
{
public partial class NWClientForm
: Form
{
public
NWClientForm()
{
InitializeComponent();
}
private
NWWebSite.NWWebService service
= new NWWebSite.NWWebService();
private void getButton_Click(object
sender, EventArgs e)
{
this.service.GetProductsAsync();
this.service.GetProductsCompleted
+= this.GetProducts_Completed;
}
private void GetProducts_Completed(object
sender,
NWWebSite.GetProductsCompletedEventArgs e)
{
this.dataset
= e.Result;
this.dataGridView1.DataSource
= this.dataset;
this.dataGridView1.DataMember
= "My Products";
}
}
}
The main effect of the asynchronous code
can be experienced when the user interface is used: it will not seem to hang,
but respond almost immediately.
Adding the UpdateProducts web method
In this stage of the tutor the user is able to
consult the data in the datagrid. When the user edits the data in the datagrid,
this will only result in data changing in the dataset on the client. The
changes will not reflect into the database on the server, unless we add some
extra code both at the client and server side.
Let us study this update mechanism of ADO.NET.
Therefore we add to the web service an extra web method UpdateProducts that has
a dataset as parameter :
<WebMethod()> _
Public Sub UpdateProducts(ByVal dataset As
DataSet)
End Sub
As the dataset parameter will contain the
changes to be updated into the database, we need again a data adapter that can
accomplish this request:
Dim
adapter As New
SqlDataAdapter
adapter.Update(dataset, "My
Products")
The adapter will only be able to update the
changes in the dataset to the database, if the adapter contains definitions for
its UpdateCommand, DeleteCommand, and InsertCommand member. We have several
options to define those updating commands, but in order to keep the tutor story
simple, we go for the CommandBuilder approach.
ADO.NET defines for each data provider a
CommandBuilder that is able to build updating commands starting from a
SelectCommand. The syntax may seem a bit strange, but what we do is simply
instantiate a CommandBuilder object passing a DataAdapter object that contains
a SelectCommand:
Dim
adapter As New
SqlDataAdapter
Dim
connection As New
SqlConnection(connectionString)
Dim
command As New
SqlCommand
command.CommandText = cmdText
command.Connection = connection
adapter.SelectCommand = command
Dim
commandbuilder As New
SqlCommandBuilder(adapter)
In its constructor, the CommandBuilder
object will create the UpdateCommand, DeleteCommand, and InsertCommand members
of the DataAdapter.
The complete code of the web service should
look like:
Option Strict On
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.Data
Imports System.Data.SqlClient
<WebService(Namespace:="http://u2u.net/webservices/")>
_
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)>
_
Public Class NWWebService
Inherits System.Web.Services.WebService
Public Sub NWWebService()
End Sub
Private Const cmdText As String = "Select * from Products"
Private Const connectionString As String =
"Data Source=U2U-WIM2;Initial Catalog=Northwind;Persist Security
Info=True;User ID=sa;password=u2u"
<WebMethod()> _
Public Function GetProducts() As DataSet
Dim dataset As New DataSet("NorthwindDataSet")
Dim adapter As New SqlDataAdapter
Dim connection As New
SqlConnection(connectionString)
Dim command As New SqlCommand
command.CommandText = cmdText
command.Connection = connection
adapter.SelectCommand = command
connection.Open()
adapter.Fill(dataset, "My Products")
connection.Close()
Return dataset
End Function
<WebMethod()> _
Public Sub UpdateProducts(ByVal dataset As
DataSet)
Dim adapter As New SqlDataAdapter
Dim connection As New
SqlConnection(connectionString)
Dim command As New SqlCommand
command.CommandText = cmdText
command.Connection = connection
adapter.SelectCommand = command
Dim commandbuilder As New
SqlCommandBuilder(adapter)
connection.Open()
adapter.Update(dataset, "My Products")
connection.Close()
End Sub
End Class
To the client from we add now a second
button, giving it the name “updateButton” and entering “Update” as text:

As event handler to the Update button we add
the following asynchronous invocation of the update web method:
private void updateButton_Click(object sender, EventArgs
e)
{
service.UpdateProducts(this.dataset);
}
In the above code snippet, the dataset is
defined as a private field of the NWClientForm in order to be shared among the
GetProducts and UpdateProducts method.
But maybe better here is also to use the
asynchronous technique where we call the UpdateProductsAsync method on the
service:
private void updateButton_Click(object sender, EventArgs
e)
{
service.UpdateProductsAsync(dataset);
}
If necessary, we can add an asynchronous
completed event handler, for example in order to disable the update button
during the update job:
private void updateButton_Click(object sender, EventArgs
e)
{
this.updateButton.Enabled = false;
this.service.UpdateProductsAsync(dataset);
this.service.UpdateProductsCompleted+=
this.UpdateProducts_Completed;
}
private void UpdateProducts_Completed(object sender,
System.ComponentModel.AsyncCompletedEventArgs e)
{
this.updateButton.Enabled = false;
}
The complete client code looks like:
using
System.Collections.Generic;
using
System.ComponentModel;
using
System.Data;
using
System.Drawing;
using
System.Text;
using
System.Windows.Forms;
namespace NWClient
{
public partial class NWClientForm
: Form
{
public
NWClientForm()
{
InitializeComponent();
}
private
NWWebSite.NWWebService service
= new NWWebSite.NWWebService();
private DataSet dataset;
private void getButton_Click(object
sender, EventArgs e)
{
service.GetProductsAsync();
service.GetProductsCompleted += this.GetProducts_Completed;
}
private void GetProducts_Completed(object
sender,
NWWebSite.GetProductsCompletedEventArgs e)
{
this.dataset
= e.Result;
dataGridView1.DataSource = this.dataset;
dataGridView1.DataMember = "My Products";
}
private void updateButton_Click(object
sender, EventArgs e)
{
service.UpdateProductsAsync(dataset);
}
}
}

The result of our coding until now is that
the user is not only able to consult the data, but also able to confirm his
updates.
Serializing the dataset in XML
Next technique that we study is the XML
serialization of datasets. We will write a dataset to an XML file and later
read that XML file in order to create a new dataset.
We only program the client side, and start
by adding two new buttons to our client form: a button named writeXmlButton
with “WriteXML” as text, and a button named readXmlButton having “ReadXML” for
its Text property.

For serializing
the dataset, we define the following paths that refer to the project path so
that we can easily open to the XML files from our client project in Visual
Studio 2005 (the paths should be adapted to your own situation):
private const string projectPath
=
@"C:\U2UTutor\ADO.NET 2.0\NorthWind\NWClient\";
private const string
xmlFile = projectPath + @"NWDataSet.xml";
private const string
xsdFile = projectPath + @"NWDataSet.xsd";
The event handlers are simple:
private void writeXmlButton_Click(object sender, EventArgs
e)
{
this.dataset.WriteXml(xmlFile);
}
private void readXmlButton_Click(object sender, EventArgs
e)
{
this.dataset =
new DataSet();
this.dataset.ReadXml(xmlFile);
this.dataGridView1.DataSource
= this.dataset;
this.dataGridView1.DataMember
= "My Products";
}
Notice that when we deserialize the
dataset, we have to instantiate a empty dataset before we can read in the XML
data.
We run the program now and clicking the buttons
in the correct order (beware of exceptions):
First we retrieve the dataset from the web service: (1) Start application, (2)
Click Get.
Then we serialize the dataset: (3) Click WriteXML and (4) stop the application
Secondly we (5) restart the application and deserialize the dataset by (6)
clicking Read XML.
In the Solution Explorer we will find our
XML file “NWDataSet.xml”:

This XML file contains the data records
only:

Another important technique is to extract
the schema out of a dataset, by means of the WriteXmlSchema method of the
dataset. Let’s first adapt the client form by adding a fifth button named
writeSchemaButton having WriteSchema as text:

In the event handler of the
writeSchemaButton we add the request that writes the schema of the dataset to
the XSD file:
private void writeSchemaButton_Click(object sender, EventArgs
e)
{
this.dataset.WriteXmlSchema(xsdFile);
}
As result of clicking the writeSchemaButton,
we obtain not only an XSD file into our project (named NWDataSet), but also an
XSC and an XSS file.

The complete code of this step looks like:
using
System;
using
System.Collections.Generic;
using
System.ComponentModel;
using
System.Data;
using
System.Drawing;
using
System.Text;
using
System.Windows.Forms;
namespace NWClient
{
public partial class NWClientForm
: Form
{
public
NWClientForm()
{
InitializeComponent();
}
private
NWWebSite.NWWebService service
= new NWWebSite.NWWebService();
private DataSet dataset;
private void getButton_Click(object
sender, EventArgs e)
{
this.service.GetProductsAsync();
this.service.GetProductsCompleted
+= this.GetProducts_Completed;
}
private void GetProducts_Completed(object
sender,
NWWebSite.GetProductsCompletedEventArgs e)
{
this.dataset
= e.Result;
this.dataGridView1.DataSource
= this.dataset;
this.dataGridView1.DataMember
= "My Products";
}
private void updateButton_Click(object
sender, EventArgs e)
{
this.service.UpdateProductsAsync(dataset);
}
private const string
projectPath
=
@"C:\U2UTutor\ADO.NET 2.0\NorthWind\NWClient\";
private const string xmlFile
= projectPath + @"NWDataSet.xml";
private const string xsdFile
= projectPath + @"NWDataSet.xsd";
private void writeXmlButton_Click(object
sender, EventArgs e)
{
this.dataset.WriteXml(xmlFile);
}
private void readXmlButton_Click(object
sender, EventArgs e)
{
this.dataset
= new DataSet();
this.dataset.ReadXml(xmlFile);
this.dataGridView1.DataSource
= this.dataset;
this.dataGridView1.DataMember
= "My Products";
}
private void writeSchemaButton_Click(object
sender, EventArgs e)
{
this.dataset.WriteXmlSchema(xsdFile);
}
}
}
We open the “NWDataSet” file in Visual
Studio 2005 and by default we are dealing with the XSD designer showing the XSD
file as an entity-relationship diagram. In our example we only see one table named
“My Products”:

Opening the XSD file in XML format, reveals
us the XSD tags defining the table fields as elements in a sequence:

Creating a typed dataset from a XSD schema
From the moment an XSD file containing a
XSD schema of a dataset is added to a project, Visual Studio 2005 immediately
generates a typed dataset. For our tutor example, we can test this by
“including” the “NWDataSet.xsd” file to the “NWClient” project:

As result, the designer generates a typed
dataset in the “NWDataSet.Designher.cs” file.

This “NWDataSet.Designer.cs file contains
the typed dataset”NorthwindDataSet” defined in the namespace NWClient. The
NorthwindDataSet inherits from the System.DataSet and contains nested classes
as the My_ProductsDataTable and the My_ProductsRow:

In order to test the typed dataset
functionality, we add to our client form a sixth button named “getTypedDsButton”
with text “Typed DS”:

In the event handler we first create a new
instance of the typed dataset “NorthwindDataSet” and merge the dataset returned
by the webservice:
NorthwindDataSet nwdataset = new NorthwindDataSet();
nwdataset.Merge(service.GetProducts());
As it is an inherited behavior, the typed
dataset can be bound immediately to the DataSource member of the DataGridView
control:
this.dataGridView1.DataSource
= nwdataset;
this.dataGridView1.DataMember
= "My Products";
But the behavior that is typical for a
typed dataset can be explored by browsing to a certain row, for example the
second row:
NorthwindDataSet.My_ProductsRow row;
row = nwdataset.My_Products.Rows[1] as NorthwindDataSet.My_ProductsRow;
In a typed dataset the fields can be
accessed by properties that correspond to field names:
MessageBox.Show(row.ProductName);
As result of this code we will receive a
messagebox showing the product name of the second product:

The final client code of this tutor looks
like:
using
System;
using
System.Collections.Generic;
using
System.ComponentModel;
using
System.Data;
using
System.Drawing;
using
System.Text;
using
System.Windows.Forms;
namespace NWClient
{
public partial class NWClientForm
: Form
{
public
NWClientForm()
{
InitializeComponent();
}
private
NWWebSite.NWWebService service
= new NWWebSite.NWWebService();
private DataSet dataset;
private void getButton_Click(object
sender, EventArgs e)
{
this.service.GetProductsAsync();
this.service.GetProductsCompleted
+= this.GetProducts_Completed;
}
private void GetProducts_Completed(object
sender,
NWWebSite.GetProductsCompletedEventArgs e)
{
this.dataset
= e.Result;
this.dataGridView1.DataSource
= this.dataset;
this.dataGridView1.DataMember
= "My Products";
}
private void UpdateProducts_Completed(object sender,
System.ComponentModel.AsyncCompletedEventArgs e)
{
}
private void updateButton_Click(object
sender, EventArgs e)
{
this.service.UpdateProductsAsync(dataset);
this.service.UpdateProductsCompleted
+= this.UpdateProducts_Completed;
}
private const string
projectPath
=
@"C:\U2UTutor\ADO.NET 2.0\NorthWind\NWClient\";
private const string xmlFile
= projectPath + @"NWDataSet.xml";
private const string xsdFile
= projectPath + @"NWDataSet.xsd";
private void writeXmlButton_Click(object
sender, EventArgs e)
{
this.dataset.WriteXml(xmlFile);
}
private void readXmlButton_Click(object
sender, EventArgs e)
{
this.dataset
= new DataSet();
this.dataset.ReadXml(xmlFile);
this.dataGridView1.DataSource
= this.dataset;
this.dataGridView1.DataMember
= "My Products";
}
private void writeSchemaButton_Click(object
sender, EventArgs e)
{
this.dataset.WriteXmlSchema(xsdFile);
}
private void getTypedDsButton_Click(object
sender, EventArgs e)
{
NorthwindDataSet nwdataset = new NorthwindDataSet();
nwdataset.Merge(service.GetProducts());
this.dataGridView1.DataSource
= nwdataset;
this.dataGridView1.DataMember
= "My Products";
NorthwindDataSet.My_ProductsRow row =
nwdataset.My_Products.Rows[1] as NorthwindDataSet.My_ProductsRow;
MessageBox.Show(row.ProductName);
}
}
}