Tải bản đầy đủ (.pdf) (13 trang)

Tài liệu Updating a Database Using a DataSet doc

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (44.46 KB, 13 trang )



Updating a Database Using a DataSet
In the exercises so far in this chapter, you have seen how to fetch data from a database.
Now it's time to show you how to update data. First, however, we need to consider some
potential problems and how using a DataSet can overcome them.
Databases are intended to support multiple concurrent users, but resources such as the
number of concurrent connections allowed might be limited. In an application that
fetches and displays data, you never know quite how long the user will be browsing the
data, and it is not a good practice to keep a database connection open for an extended
period of time. Instead, a better approach is to connect to the database, fetch the data into
a DataSet object, and then disconnect again. The user can browse the data in the DataSet
and make any changes required. After the user finishes, the program can reconnect to the
database and submit any changes. Of course, there are complications that you need to
consider, such as what happens if two users have queried and updated the same data,
changing it to different values. Which value should be stored in the database? We will
come back to this problem shortly.
Managing Connections
In earlier exercises, you have seen that when you define a DataSet you can specify a
connection to use for communicating with the database. This information is embedded
into the TableAdapter used to retrieve the data and fill the DataSet. When you execute the
Fill or GetData methods, the code generated by Visual Studio 2005 examines the state of
the connection first. If the connection to be used is already open, it is used to retrieve the
data, and is left open at the end of the operation. If the connection is closed, the Fill and
GetData methods open it, fetch the data, and then close it again. The DataSet in this case
is referred to as a disconnected DataSet as it doesn't maintain an active connection to the
database. Disconnected DataSet objects act as a data cache in applications. You can
modify the data in the DataSet, and later reopen the connection and send the changes
back to the database.
You can manually open a connection to a database by creating a SqlConnection object,
setting its ConnectionString property, and then calling its Open method as shown in


Chapter 23. You can associate an open connection with a TableAdapter by setting the
Connection property. The following code shows how to connect to the database and fill
the Suppliers DataTable. In this case, the database connection will remain open after the
Fill method completes:
SqlConnection dataConnection = new SqlConnection();
dataConnection.ConnectionString = "Integrated Security=true;" +
"Initial Catalog=Northwind;" +
"Data Source=YourServer\\SQLExpress";
dataConnection.Open();
suppliersTableAdapter.Connection = dataConnection;
suppliersTableAdapter.Fill(northwindDataSet.Suppliers);
Unless you have a good reason to do so, you should avoid maintaining connections
longer than needed; let the Fill and GetData methods open and close the connection for
you and create a disconnected DataSet.
Handling Multi-User Updates
Earlier in this chapter, we mentioned the problem that arises if two users try and update
the same data at the same time. There are at least two possible approaches you can adopt
to solve this problem. Each approach has its benefits and disadvantages.
The first technique involves the Use optimistic concurrency option in the the Advanced
Options dialog box in the TableAdapter Configuration Wizard.

If you deselect this option, the rows retrieved into the DataSet will be locked in the
database to prevent other users from changing them. This is known as pessimistic
concurrency. It guarantees that any changes you make will not conflict with changes
made by any other users at the expense of blocking those other users. If you retrieve a
large number of rows and only update a small proportion of them, you have potentially
prevented other users from modifying any of the rows that you have not changed. There
is one other drawback—locking data requires that the connection used to retrieve the data
remains open, therefore if you use pessimistic concurrency you also run the risk of
consuming a large number of connection resources. The principal advantage of

pessimistic concurrency, of course, is simplicity. You don't have to write code that
checks for updates made by other users before modifying the database.
If you select the “Use optimistic concurrency” option, data is not locked, and the
connection can be closed after the data has been fetched. The disadvantage is that you
have to write code that ascertains whether any updates made by the user conflict with
those made by other users, and this code can be quite difficult to write and debug.
However, the TableAdapter object generated by the TableAdapter Configuration Wizard
hides much of this complexity, although you must be prepared to handle the events that
can be raised if conflicts occur. We will look at this in more detail in the final part of this
chapter.
Using a DataSet with a DataGridView Control
Now that you have a good understanding of how to create DataSet objects, retrieve rows,
and display data, you are going to add functionality to the Products Maintenance
application to allow the user to update the details of Products in the database. You will
use a DataGridView control for displaying and updating the data.
Add the DataGridView control to the form
1. Display ProductsForm in the Design View window. Delete the supplierList
ComboBox control and the supplierID Label control from the form.
2. In the Code and Text Editor window, remove the
supplierList_SelectedIndexChanged method from ProductsForm.cs.
3. Return to the Design View window. Resize the form; set its Size property to 600,
400.
4. In the Toolbox, expand the Data category, and click the DataGridView control.
Drop the control onto the form. Rename the DataGridView control as
productsGrid. Set its Location property to 13, 61 and its Size property to 567, 300.
5. Add two Button controls to the form above productsGrid and set their Location
properties to 402, 22 and 505, 22. Rename them as queryButton and saveButton.
Change the Text property of each button to Query and Save, respectively.
The next step is to create a DataAdapter class and bind it to the DataGridView control.
You will create the DataAdapter class by using the TableAdapter Configuration Wizard.

To add a bit of variation, rather than setting the DataSource and DataMember properties
of the DataGridView control by using the Design View window, you will bind to the
DataAdapter by writing some code.
Create a DataAdapter for fetching Products and bind it to the DataGridView control
1. Display the DataSet Design window for NorthwindDataSet.xsd (double-click
NorthwindDataSet.xsd in the Solution Explorer).
2. Add a new TableAdapter to the DataSet by using the TableAdapter Configuration
Wizard for fetching the details of Products from the Northwind database. Use the
information in the following table to help you.
Page Field Value
Choose Your
Data
Connection
Which data connection should
your application use to connect
to the database?
NorthwindConnectionString
Choose a
Command Type
How should the TableAdapter
access the database?
Use SQL statements
Enter a SQL
Statement
What data should be loaded
into the table?
SELECT * FROM Products
Page Field Value
Advanced Options Select all options
Choose

Methods to
Generate
Which methods do you want to
add to the TableAdapter?
Select all options and use default
method names
3. When you complete the wizard and the DataTable and TableAdapter are
generated, notice that the wizard automatically detects that the Suppliers and
Products table have a relationship in the database and creates a Relation that links
the DataTables together.
4. In the Build menu, click Rebuild Solution to generate the code for the new
DataTable and TableAdapter classes.
5. Display ProductForm in the Design View window. Double-click the Query Button
control.
Visual Studio 2005 generates a click event handler for the control called
queryButton_Click and places you in the Code and Text Editor window.
6. Add the following statements to the queryButton_Click method:
7. NorthwindDataSetTableAdapters.ProductsTableAdapter productsTA =
8. new NorthwindDataSetTableAdapters.ProductsTableAdapter();
9. productsTA.Fill(northwindDataSet.Products);
10. BindingSource productsBS = new BindingSource(northwindDataSet, "Products");
productsGrid.DataSource = productsBS;
The first statement creates a new instance of the ProductsTableAdapter class that
you defined by using the TableAdapter Configuration Wizard. Notice that this
class is defined in a namespace called NorthwindDataSetTableAdapters (as are all
the other TableAdapter classes for this DataSet). The second statement uses this
object to fill the Products DataTable in the northwindDataSet object. Remember
that this statement will automatically disconnect from the database after fetching
the data because no prior connection had been established. The third statement
creates a new BindingSource object for the Products DataTable in the

northwindDataSet object. The fourth statement actually performs the data
binding—it sets the DataSource property of the DataGridView control to refer to
the new BindingSource object.
11. Build and run the application.
When the application starts, the DataGridView control is initially empty.
12. Click Query. The DataGridView displays a list of Products. Verify that the
number of rows in the DataGridView control matches the value displayed by the
Number of Products label.

13. Click the ProductName column header. The rows are sorted by product name and
appear in ascending order. Click the ProductName column again. This time the
rows appear in descending order. Click the ProductID column to display the rows
in their original order.
14. Click any cell in the DataGridView and overtype the data. By default, you can
modify the contents of any cell other than the ProductID. You cannot change the
ProductID of a row because this column is marked as the primary key of the table
in the database (primary key values should never be updated as they are used to
identify a row in the database).
Try typing an invalid value into a cell—type an alphabetic string into the
SupplierID column, for example. When you click away, an error dialog will be
displayed. This is the default error handling dialog for the DataGridView control
(and is rather ugly). You can replace it with your own code by trapping the
DataError event of the DataGridView control. Press the Escape key to undo the
change.
15. Scroll right to display the Discontinued column. Notice that this column appears
as a check box. In the database, this column has the bit type, and can only contain
two values (1 or 0).
16. Scroll to the end of the data in the DataGridView control. A row marked with an
asterisk appears. You can add a new product by entering its details in this row.
Notice that the ProductID is generated automatically.

17. Click in the gray margin on the left-hand side of row 76. The entire row is
highlighted. Press the Delete key. The row disappears from the DataGridView
control.
18. When you have finished browsing the data, close the form and return to Visual
Studio 2005. No changes will be saved as you have not yet written the code to do
this.
Validating User Input in the DataGridView Control
Before saving changes back to the database, we want to ensure that the changes the user
makes are valid. Currently, the user can type any amount of rubbish into the
DataGridView. In the next exercises, you will learn how to constrain the user input to
eliminate some possible sources of error, and validate the data in the control.

×