Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 69 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
69
Dung lượng
626,68 KB
Nội dung
Data Access with ADO.NET 27 We can also add a UniqueConstraint to the ConstraintCollection to ensure that the primary key of a column is unique. This is a very similar process to setting the primary key shown earlier. ' Declare a ConstraintCollection. Dim myCKey As ConstraintCollection Dim myColumn As DataColumn ' Get the column we want to place a unique constraint on. myColumn = myDataSet.Tables("Customers").Columns("CustomerID") ' Add the constraint to the constraint collection. myCKey.Add("MyConstraint", myColumn, True) ' Add the constraint collection to the table's constraint collection. myDataSet.Tables("Customers").Constraints.Add(mCKey) This code starts with declarations for a ConstraintCollection and a DataColumn object to hold the column we want to set the constraint for (in this case the CustomerID column). We use the Add method of the ConstraintCollection, passing in the name of a constraint, the DataColumn object, and a Boolean parameter indicating if this is a primary key. We then call the Add method of the Tables.Constraints property and pass in the ConstraintCollection object. There are many objects that work together to make up the DataSet object. They all work hand and hand to build the tables' schema as well as manage the data. Next we will see how to save changes that are made to a DataSet on the server. Updating the Database Once changes are made to a DataSet how do we update those changes back to the database? Earlier we showed how calling the AcceptChanges method updates only local records and not the database proper. These methods we use next assume you haven't called AcceptChanges on any of your modified records before you post changes to the server. We have a couple of methods for updating our database. To update a DataSet call the Update method of the DataAdapter. This can take a DataSet, DataTables, or an array of DataRow objects, and examines the RowState property to determine which rows have changed. Then Insert, Update, or Delete is executed depending on the state of the changed row. When you call a DataAdapter's Update method, you update your changes on the server. As you can see from the illustration below, we follow a similar process as with the AcceptChanges method: Data Access with ADO.NET 29 We can control which updates are completed first if we need to. By default, the DataAdapter will update each row depending on its order, one row could be deleted and the row after it added. We can use the GetChanges method of a DataSet or DataTable to control which updates we want to occur first. GetChanges returns a DataSet containing changes that match the RowState parameter you specify, thus allowing us to retrieve only records marked as modified, deleted, or inserted, as the code below shows: Dim myDataSetChanges As New DataSet() ' Gets all changes. myDataSetChanges = myCustomerDataSet.GetChanges() ' Get records that have been modified only. myDataSetChanges = myCustomerDataSet.GetChanges(DataRowState.Modified) ' Get records that have been deleted only. myDataSetChanges = myCustomerDataSet.GetChanges(DataRowState.Deleted) ' Get records that have been added only. myDataSetChanges = myCustomerDataSet.GetChanges(DataRowState.Inserted) ' Update changes back to actual database. myDataAdapter.Update(myDataSetChanges) Once we have a DataSet with only records that have changed, we call the DataAdapter's Update method passing in this DataSet as shown above. This allows you to perform updates where you have referential integrity. Let's say you have a Customer table and an Address table and the Address table contains the primary key of the customer. You would want to delete the addresses before the customer otherwise you could experience an error. If we were to delete the customer first, we would have a record that points to another record that doesn't exist. This would leave "orphaned" records in the database that referential integrity prohibits. A related method is the Merge method, which merges one DataSet into another keeping all the original DataSet's row state information: ' Create a new dataset with only the modified records. Dim myDataSetChanges As New DataSet() myDataSetChanges = myCustomerDataSet.GetChanges(DataRowState.Modified) ' Merge the changes back into our local dataset. myNewDataSet.Merge(myDataSet) ' Commit the changes. myNewDataSet.AcceptChanges() When we call the Merge method passing in myDataSet, any records in the DataSet are added to myNewDataSet that now has the records that were in myDataSet along with the row state information of each record. This is useful when we get data from an outside source or a source not part of our system that we want to merge into our current set of data. Once we call the AcceptChanges method of myNewDataSet, we no longer have a modified RowState and we lose any changes we may have had. Chapter 6 30 As a final note, you must ensure you have updated your changes back to the database by calling the Update method of your DataAdapter, otherwise the changes will be lost. This must be done before the AcceptChanges method is called since AcceptChanges clears any and all row states. The Update needs the row state information to determine which records need updating. DataSet Sample Next, we will expand the customer application created in the last chapter to add the capability to insert, update, and delete data. As it currently stands, our application provides a read-only view of the database. This is only a quick sample: we will develop a more complex application in later chapters. Here is what our final result will look like: Try It Out – Reconfiguring the DataAdapters 1. Open the project from the previous chapter called CustomerApp. We need to re-configure the data adapter for our customer table so we can perform Insert, Update, and Delete commands on the table. Right-click on SqlDataAdpter1 and select Configure Data Adapter. Data Access with ADO.NET 31 2. The Data Adapter Configuration Wizard dialog will appear prompting for a connection to a database. The name of our previous connection should appear which will be listed as Servername.Northwind SQL.dbo where Servername is the name of your particular computer. If the connection doesn't appear, create a new connection by clicking on the New Connection button. Click Next when you're finished. 3. The Use SQL statements option should already be selected. Ensure that it is and click Next. Chapter 6 32 4. The existing SQL SELECT statement should appear on the next pop up window. As we are now going to insert, update, and delete records, we want to enable the wizard's automatic generation of INSERT, UPDATE, and DELETE commands. Click the Advanced Options button. 5. The advanced dialog gives us three options. Select the first check box, which will enable the rest of the check boxes. We want all of the options selected. Click OK when you're finished. Data Access with ADO.NET 33 Review the SELECT statement on the next screen and click Next. 6. The last screen to be shown is a review of what will be built, and it should indicate that we are going to generate INSERT, UPDATE, and DELETE statements. Click the Finish button. 7. Repeat the above steps for the second data adapter, SqlDataAdapter2, so that we will be able to make changes to the Suppliers table. Try It Out – Update 8. Add a new button to the form and call it btnUpdateData. Set the Text property to Update. Add one more button to the form and call it btnShowChanges. Set its Text property to Show Changes. Chapter 6 34 9. The Update button we added will be used to update any changes we have made to the records in our DataGrid. The Show Changes button will show us any changes we have made to the data. Add some code to the click event of the Update button by double-clicking on the button: Private Sub btnUpdateData_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnUpdateData.Click Dim RecordsUpdated As Integer If CustomerDataSet1.HasChanges Then ' Update any customer table changes. RecordsUpdated = SqlDataAdapter1.Update(CustomerDataSet1) MessageBox.Show(RecordsUpdated.ToString & " customer record(s) updated.") ' Update any supplier table changes. RecordsUpdated = SqlDataAdapter2.Update(CustomerDataSet1) MessageBox.Show(RecordsUpdated.ToString & " supplier record(s) updated.") ' Refresh the grid. btnGetData_Click(sender, e) Else MessageBox.Show("There are no changed records to update.") End If End Sub 10. Add some code to the click event of the Show Changes button by double-clicking on the button. Private Sub btnShowChanges_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnShowChanges.Click ' Make sure we have changes to show. If CustomerDataSet1.HasChanges = False Then MessageBox.Show("There are no changed records to show.") Exit Sub End If ' Create a dataset with all changes. Dim myDataSet As New DataSet() myDataSet = CustomerDataSet1.GetChanges() ' Make sure we have no errors. If myDataSet.HasErrors = 0 Then ' Show only the changed records. DataGrid1.DataSource = Nothing DataGrid1.DataSource = myDataSet End If End Sub Data Access with ADO.NET 35 11. Add some code to re-bind the DataSource to our original DataSet and to expand the rows: Private Sub btnGetData_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnGetData.Click ' If connection isn't open then open it. If SqlConnection1.State <> ConnectionState.Open Then SqlConnection1.Open() ' Fill our customer table. SqlDataAdapter1.Fill(CustomerDataSet1) ' Fill our suppliers table. SqlDataAdapter2.Fill(CustomerDataSet1) ' If connection isn't closed then close it. If SqlConnection1.State <> ConnectionState.Closed Then SqlConnection1.Close() End If ' Rebind data source in case its not bound to original dataset. DataGrid1.DataSource = Nothing DataGrid1.DataSource = CustomerDataSet1 ' Expand all the child rows. DataGrid1.Expand(-1) End Sub How It Works First let's look at the code we added under the Update button. We start by checking to see if the CustomerDataSet1 DataSet has any changes in any of the tables that it contains and, if there are any changes, we update the database server by calling the Update method of both DataAdapters. If there are no changes, then these methods won't be called. If CustomerDataSet1.HasChanges Then ' Update any customer table changes. RecordsUpdated = SqlDataAdapter1.Update(CustomerDataSet1) We show the number of records updated by passing back the result from the Update method. MessageBox.Show(RecordsUpdated.ToString & " customer record(s) updated.") The same goes for the supplier table; we call the Update method of SqlDataAdapter2 and display the number of records as well. ' Update any supplier table changes. RecordsUpdated = SqlDataAdapter2.Update(CustomerDataSet1) MessageBox.Show(RecordsUpdated.ToString & " supplier record(s) updated.") Chapter 6 36 Once we update any changes, we refresh the DataGrid by calling the Get Data button's click method: ' Refresh the grid. btnGetData_Click(sender, e) Now let's see the code behind the Show Changes button in the btnShowChanges_click event that shows only changed records: ' Make sure we have changes to show. If CustomerDataSet1.HasChanges = False Then MessageBox.Show("There are no changed records to show.") Exit Sub End If ' Create a dataset with all changes. Dim myDataSet As New DataSet() myDataSet = CustomerDataSet1.GetChanges() ' Make sure we have no errors. If myDataSet.HasErrors = 0 Then ' Show only the changed records. DataGrid1.DataSource = Nothing DataGrid1.DataSource = myDataSet End If First we check to see if there are any changes in our DataSet, CustomerDataSet1, and display a message box to the user indicating that no changes have been made if that is the case. When we show our changed records in the DataGrid, we are binding it to a DataSet that contains just the changed records. We do this by calling the GetChanges method of our customer DataSet. This method returns a new DataSet with only changed records; we then verify that it doesn't contain any errors by checking the HasErrors property. The HasErrors property can be used for DataRow, DataTable, and DataSet objects, so you are not limited to just checking errors for whole DataSets. As long as there are no errors, we display the contents of the changed DataSet, myDataSet, in the DataGrid. We then call the Expand method of DataGrid1 to display any child rows. Once you view the changed records, you can click the Update button to save the changes to the database. If you don't click the Update button but instead click the Get Data button, the DataGrid is refreshed with a new DataSet and, as a result, any changes that you may have made will be lost. Lastly, we added code in the Get Data button. To view our original DataSet we have to re-assign the original DataSet, CustomerDataSet1, back to the DataGrid. We first set the DataSource to Nothing to clear any existing DataSource. ' Rebind data source in case its not bound to original dataset DataGrid1.DataSource = Nothing DataGrid1.DataSource = CustomerDataSet1 We then call the DataGrid's Expand method, using a value of -1 to expand all the child rows. We can also expand an individual row by passing in a number representing that row. ' Expand all the child rows. DataGrid1.Expand(-1) Now that we have added code to actually update our DataGrid information, let's go ahead and try it out. [...]... the database, then you will also need those two pieces of information Now let's take a look at some sample connection strings This one connects to a Microsoft Access database: "Provider=Microsoft.Jet.OLEDB .4. 0;Data Source=C:\Samples\Northwind.mdb;User ID=;Password=;" This one connects to an Oracle database: "Provider=MSDAORA;Data Source=MyOracleDB;User ID=myID;Password=myPWD;" 46 Data Access with ADO.NET... support for OLE DB Provider (use the SQL Data Provider instead of OLE DB Provider for SQL Server) There is no future need for other database types besides Microsoft SQL Server (SQL Server 7.0 and above) You need support for any native ODBC drivers 44 Data Access with ADO.NET To use the OLE DB data provider in your project, you must include the OleDb namespace in your code modules: Imports System.Data.OleDb... Dataflow in ADO.NET Now that we have discussed the components of ADO.NET, let's see how they complement each other and how they would flow in a real world application The data tier contains the data source, to which the managed provider must connect to retrieve information and fill our tables with information as requested by the client The following figure summarizes the basic components of ADO.NET: Middle... Integer = 4 Const DISCONTINUED_COLUMN As Integer = 5 60 Data Access with ADO.NET Next, we created a new SqlConnection object and assigned a connection string to the ConnectionString property This includes the name of the server we are connecting to (here we use localhost, but this may vary depending on where your SQL Server is situated), the name of the database we want to connect to (the NorthwindSQL database) ,... generated The connection string has several commonly used properties: 45 Chapter 6 Property Default Value Description Provider (Required) Used with OLE DB provider only Specifies the provider to use Data Source or Server (Required) The name of the server to connect to, for example: localhost, MYSERVER Initial Catalog or Database (Required) The database to connect to, for example: Northwind, Pubs User ID (Required... we communicate with the database, and which is specific to this solution The System.Data assembly is used to retrieve the data directly from the database ❑ Lastly we have the client tier, where the users interface with our system; this is sometimes referred to as the presentation tier The client tier could comprise a Windows or web application that interacts with the system .NET Data Providers The... procedures for a DataAdapter object There are two types, OleDbCommand and SqlCommand, and four subtypes: SelectCommand, InsertCommand, UpdateCommand, and DeleteCommand 48 Data Access with ADO.NET This object is used to send commands to a database by way of a connection object Dim myConnection As New SqlConnection(myConnString) Dim myAdapter As New SqlDataAdapter() Dim mySelectQuery As String = "SELECT... reorder levels are a field in the database like any other, so your interface application would allow users to adjust this value as appropriate, just as any other column The stock check program could be configured to email someone when stock drops below certain thresholds You can learn about emailing, services, and other advanced features in Wrox Press's Professional Visual Basic NET How It Works First,... their underlying classes If we examine the properties of the System.Data reference, we can see the assembly's name, description, location, and version information: 40 Data Access with ADO.NET Let's take a look at the five commonly used ADO.NET namespaces: System Data OleDb SqlClient XML ❑ System – the core namespace that contains the fundamental classes and base classes that define commonly used value...Data Access with ADO.NET Try It Out – Updating DataGrid Information 1 Compile and run the application using the F5 key 2 Click the Get Data button 3 Expand the node if not already expanded so that the Customer and Supplier links show 4 Select the Customers link and modify the second PostalCode record from 05021 to 05023 5 Click . our records with very little code. Chapter 6 40 ADO .NET Namespaces In this next section, we will look at the different namespaces that make up ADO .NET and how they are used. Namespaces help identify. name, description, location, and version information: Data Access with ADO .NET 41 Let's take a look at the five commonly used ADO .NET namespaces: System Data OleDb SqlClient XML ❑ System – the core. ADO .NET and XML in further detail, and the classes listed above will be used throughout the final chapters of this book. Dataflow in ADO .NET Now that we have discussed the components of ADO .NET,