We specifically learned about: ❑ Complex data binding to bind controls to more than one element in a DataSet ❑ Simple data binding to bind to the property of a control to a single elemen
Trang 1Dim strSQL As String = "SELECT * FROM Products"
Then, we open a new SQLConnection using the connection string
Dim sqlConn As New SqlClient.SqlConnection(strConnection)
sqlConn.Open()
The myCommand data command is created by passing it the statement and connection strings We canthen use myCommand to cause the DataReader to execute the SQL statement that we want – in thiscase, to select all records from the Products table
Dim myCommand As New SqlClient.SqlCommand(strSQL, sqlConn)
myCommand.CommandType = CommandType.Text
Dim myReader As SqlClient.SqlDataReader = myCommand.ExecuteReader()
However, as we learned previously, the DataReader retrieves the records one at a time in a only and read-only format
forward-The last part of code retrieves each record in the DataReader one at a time and writes the Product Idand Product Name to the Output window using the Console.WriteLine method:
Do While myReader.Read
Console.WriteLine("Product Id: " & myReader.GetInt32(0) & _
vbTab & "Product Name: " & myReader.GetString(1))
Loop
Notice the use of the GetInt32 and GetString methods of the DataReader object These methodscan be used because we know the data types of the underlying data fields By explicitly using the typedaccessor methods in this way, we reduce the amount of type conversion that is required when retrievingthe data
Last of all, we have the line that closes the DataReader
myReader.Close()
It is very important to note that a DataReader is open until you close the connection with such a line
of code (or the object gets destroyed and thus the connection is closed at some point during garbagecollection)
You can modify this simple example for your own purposes, but this should give you an idea of how to
a DataReader can be used to rapidly retrieve forward-only, read-only data The most important idea
to take away from this section is that you should use a DataReader whenever possible, and especiallywhen an in-memory copy of data is not required
Trang 2In this chapter we've covered some crucial data binding concepts as we further developed our ProductManagement System We bound our search results to the DataGrid and added the functionality toallow the user to open a specific record in the results list on the Add/View/Edit Products or Suppliersscreens We specifically learned about:
❑ Complex data binding to bind controls to more than one element in a DataSet
❑ Simple data binding to bind to the property of a control to a single element in a DataSet
❑ Creating the Base Data Form for our Product Management System
❑ Creating the Add/View/Edit Products and Suppliers Screens that inherit functionality fromthe Base Data Form
❑ Customizing the Add/View/Edit Screens for their specific needs
❑ Validating user input using the ErrorProvider Control
❑ Filtering and sorting data using DataViews
❑ Returning records using the DataReader
You should have a pretty good understanding of how to implement complex and simple data bindingand should also have working Search Screens In the next chapter, we will continue with the
development of our application and begin implementing functionality to allow the user to update datafrom the Add/View/Edit Products and Suppliers screens
Exercises
3. What is the difference between complex data binding and simple data binding? Where does
property binding fit in?
4. Briefly describe the ErrorProvider control and what it can allow you to accomplish
5. What is the purpose of a DataView?
6. Briefly describe the DataReader and when it can be used Can you bind a DataReader to
controls on a form such as a DataGrid? When should you use a DataReader versus aDataSet?
Answers are available at http://p2p.wrox.com/exercises/
Trang 5Handling Errors
In this chapter, we continue developing our Product Management System where we left off in theprevious chapter We will focus on updating data in the DataSet and then on the underlying databasebased on changes made by the user More specifically, we will learn about:
❑ Updating a DataSet based on user input
❑ Allowing the user to add, edit, and delete data in the DataSet on the Add/Edit/View
Products and Suppliers screens
❑ Creating a second dataset that contains all changes made by invoking the GetChangesmethod
❑ Checking for errors in the changed dataset by checking the HasErrors property
❑ Saving the changes in the DataSet back to the database using Stored Procedures
❑ Accepting or rejecting the changes made based on whether the updates were successful
❑ Handling any errors that occur
Updating the Local Version of the DataSet
We now know to update local DataSet that the DataSet is an in-memory copy of data that is notconnected to the database from which its contents have come Thus, if you modify the contents of aDataSet you are not actually updating the data in the underlying data store unless you take additionalsteps We will start the latest round of changes to our Product Management System by adding code toenable changes to be made to the local DataSet Then, we will implement the mechanism that savesall the changes back to the original data source when the user clicks the Save All button
Trang 6Modifying the Add/View/Edit Products and Suppliers
Screens to Update the Local DataSet
In this section, we will modify frmManageProducts.vb and frmManageSuppliers.vb to enablethe updating and deleting of data in the local DataSet
Adding a New Record to the Local DataSet
Let's start with writing the code to add a new record to the local DataSet on both the Add/View/EditProducts and Add/View/Edit Suppliers forms
Try It Out – Adding a New Record to the DataSet for the Products Screen
1. First, add this code to the Click event of the btnAdd Button on the frmManageProducts form:
Private Sub btnAdd_Click(ByVal sender As System.Object, ByVal e As _
System.EventArgs) Handles btnAdd.Click
Try
'Use the NewRow to create a DataRow in the DataSet
Dim myRow As DataRow
Trang 72. Next, we will add similar code to the Click event of the btnAdd Button on the
frmManageSuppliers form:
Private Sub btnAdd_Click(ByVal sender As System.Object, ByVal e As _
System.EventArgs) Handles btnAdd.Click
Try
'Use the NewRow to create a DataRow in the DataSet
Dim myRow As DataRow
Trang 8Deleting a Record in the Local DataSet
Next, let's move on to adding the code to delete the record in the local DataSet when the user clicksthe Delete Button on either form
Try It Out – Adding Code to Delete Records in the Local DataSet
1. Save all changes to the MainApp solution and then close it Next, open the BaseFormssolution The Delete event is the same for both Products and Suppliers, so we are going toadd it to the base form Place the following code under the Click event for the Delete Button
on the BaseDataForm.vb:
Private Sub btnDelete_Click(ByVal sender As System.Object, ByVal e As _
System.EventArgs) Handles btnDelete.Click
Try
'Delete the current row from the DataSet
Dim oRow As DataRow
Dim oTable As DataTable
Dim intResponse As Integer
intResponse = MsgBox("Are you sure you want to delete the " & _
"current record from the DataSet?", _
MsgBoxStyle.YesNo, "Confirm Delete")
'If they confirm they want to delete, then go ahead and remove
'the record from the DataSet Reminder that this still doesn't
'delete it from the database That occurs under the SaveAll
'when all changes in the DataSet are updated in the database
If intResponse = vbYes Then
Trang 92. After you complete the changes above in the BaseDataForm, save the solution and rebuild
the project by selecting Build | Rebuild All Then you can close the BaseForms solution andreturn to the MainApp solution
3. At this point, go ahead and run your project and conduct a search based on Products
Double-click on a record in the results grid to open the Add/View/Edit Products screen
Trang 104. Make changes to data and click the NextRecord Button.
5. Move back and you will see that your
changes are still in the local DataSet
Also, navigate to a record and click the
Delete button
You should see it disappear from the navigation
6. Furthermore, when you click the Add New
Record button, you should find that you are
moved to a new record with blank values
Trang 11How It Works
The purpose of this code is to delete the current record from the local DataSet when the user clicksthe Delete Button on either the Add/View/Edit Products or Suppliers forms Before deleting the record,the user is prompted to confirm the deletion
intResponse = MsgBox("Are you sure you want to delete the " & _
"current record from the DataSet?", _
MsgBoxStyle.YesNo, "Confirm Delete")
If they respond Yes, then the Delete method for the DataRow is called to delete the record from theDataSet
If intResponse = vbYes Then
oTable = dsSearchResults.Tables("results")
oRow = oTable.Rows(myBindingManagerBase.Position)
If Not oRow.RowState = DataRowState.Deleted Then _
oRow.Delete()
Recall that by deleting the record from the DataSet, the record still hasn't been deleted in the
underlying database Changes in the DataSet only get changed in the local in-memory copy of thedata We will later write the code to update the changes in the database itself
Modifying an Existing Record in the Local DataSet
In order to modify an existing record in the local DataSet, there is no extra code that you have toimplement By having the simple binding to each control property (set up in Chapter 8), this happensautomatically In other words, if you navigate through the Add/View/Edit Products screen changingdata, when you move back to the record, it will still have your changed value in that local copy It hasnot been updated in the database, at that point, however
Let's take a look at an example of this in action
Try It Out – Modifying Records in the Local DataSet
1. Open the Suppliers Search Utility and run a search for all Suppliers with a Supplier Id LessThan 5 Double-click on one of the records in the list (Supplier Id 1 if you have it in yourresults) so that the Add/View/Edit Suppliers screen is shown with the selected record active, asshown below:
Trang 122. Take note of the current value for Company Name and Home Page In the example above,
the original value for the Company Name is Exotic Liquids and the Home Page is empty.Let's change the Company Name value to Exotic Liquids 2 and add a Home Page of
www.somewhere.com After making these changes, move to the next record by clicking theNext Record Button Move to the previous record, and you should be back on the record youchanged Notice how the values contain the changes you just made:
Trang 133. Close the Add/View/Edit Suppliers form and return to the Supplier Search Utility You willeven see that the record was updated in the DataGrid, as shown below:
Trang 15myDataAdapter.SelectCommand = "SELECT * FROM Products"
myDataAdapter.UpdateCommand = "UPDATE Products SET " & _
"ProductName = 'Test' WHERE ProductId = 1"
myDataAdapter.InsertCommand = "INSERT INTO Products " & _
"(ProductName,CategoryId) VALUES ('Test', 1) "
myDataAdapter.DeleteCommand = "DELETE FROM Products " & _
Dim objCommandBuilder As New SQLCommandBuilder(myDataAdapter)
DataSet These two methods only affect the local DataSet and not the data in the actual database
Using the Update method, AcceptChanges and RejectChanges follow the principles of
transactions A transaction is a process that must either complete successfully or fail totally We
would not want the update process to finish half way through, for instance Transactions are
covered in more detail in the next chapter.
The above is the typical process flow for saving changes in a DataSet back to the database However,there are some exceptions when all of these steps will not work One example is when your DataSetwas originally populated into a single table from the results of a SELECT statement joining multipletables together In such a case, you cannot invoke the Update method of the SQLDataAdapter objectbecause it doesn't know which underlying table you want to update Thus, you have to manually updatethe records in the database while looping through the changed DataSet
If you recall, this is exactly the type of scenario we have with our Product Management System Thesearch results are based on a SQL statement that selects the records from multiple tables to make asingle table in the DataSet called Results Thus, instead of being able to easily update the databasewith changes in the DataSet just by invoking the Update method, we have to write our own loopingcode to perform the database changes Let's get started and see exactly how that works
Handling Changed Records
For starters, we need to handle existing records in the DataSet that have been modified
Trang 16Try It Out – Saving Changed Records in the DataSet to the Database
1. Place the following code under the frmManageProducts.vb form.
Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As _ System.EventArgs) Handles btnSave.Click
Try
MoveFirst()
Dim clsDb As New clsDatabase()
clsDb.ProcessUpdates(CONN, PROD, dsSearchResults)
clsDb = Nothing
MsgBox("Save Completed If no other messages appeared " & _ "indicating any errors, then all changes were successful.") Catch
'Error handling goes here
UnhandledExceptionHandler()
End Try
End Sub
2. Place this nearly identical code under the frmManageSuppliers.vb form:
Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As _ System.EventArgs) Handles btnSave.Click
Try
MoveFirst()
Dim clsDb As New clsDatabase()
clsDb.ProcessUpdates(CONN, SUPP, dsSearchResults)
clsDb = Nothing
MsgBox("Save Completed If no other messages appeared " & _ "indicating any errors, then all changes were successful.") Catch
'Error handling goes here
UnhandledExceptionHandler()
End Try
End Sub
3. Place the code for the ProcessUpdates method in clsDatabase
Sub ProcessUpdates(ByVal strConnection As String, ByVal strUpdateTable _
As String, ByRef dsdata As DataSet)
Trang 17'The purpose of this procedure is to call the database updates for
'Products or Suppliers based on the changes in the dataset
'The strUpdateTable variable passed in should be either "Products" or
'"Suppliers" for the value and depending on the value of it, the
'appropriate database updates will be called This is a
'generic routine to keep code duplication to a minimum
'Update the changes in the database
If strUpdateTable = "Products" Then
4. Add the following procedure to the clsDatabase:
Sub HandleDataSetErrors(ByVal dsChanged As DataSet)
Try
'Invoke the geterrors method to return an array of DataRow
'objects with errors
Dim ErrorRows() As DataRow
Dim oRow As DataRow
ErrorRows = GetAllErrors(dsChanged)
'On each DataRow, examine the RowError property
Dim i As Integer
Dim strError As String
strError = "The following errors occurred - "
For i = 0 To ErrorRows.GetUpperBound(0)
strError = strError & " Row Error: " & _
Trang 185. Then add the GetAllErrors function after the previous method:
Function GetAllErrors(ByVal rsChanges As DataSet) As DataRow()
Try
Dim rowsInError() As DataRow
Dim myTable As DataTable
Dim i As Integer
Dim myCol As DataColumn
For Each myTable In rsChanges.Tables
' See if the table has errors If not, skip it
6. Create that UpdateProductsInDb procedure now, in clsDatabase:
Sub UpdateProductsInDb(ByVal strConnection As String, ByVal _
dsChangedDataSet As DataSet)
'**************************************************************** 'The purpose of this function is to update data in the Products 'table based on information in a DataSet that changed
'**************************************************************** Try
Dim oRow As DataRow
Dim smallintDiscontinued As Int16
Dim intRowsAffected As Integer
For Each oRow In dsChangedDataSet.Tables("Results").Rows
Trang 19smallintDiscontinued = oRow("Discontinued")
'Format to the format that SQL Server expects
'The equivalent to Boolean in SQL Server is BIT
'A Bit can have 1 for True or 0 for False
'A Boolean in VB can have -1 for True or 0 for False
If smallintDiscontinued = vbYes Then
7. Add this procedure to clsDatabase
Sub AddProductsInsertUpdateParameters(ByRef cmdCommand As _
SqlClient.SqlCommand, ByVal oRow As DataRow, ByVal _
smallintdiscontinued As Int16, ByVal blnAddProductId As _
Boolean)
'The purpose of this procedure is to add the parameters to the
'command object that will be passed to the stored procedure for
'Updating OR Inserting Products
Try
Dim sqlparm As New SqlClient.SqlParameter()
'If updating a record, then will need to specify the ProductId
'If inserting, then one will not have been assigned yet (and
'thus the insert stored procedure doesn't expect it as a '
Trang 20Function ExecuteSPWithParameters(ByVal strConnection As String, ByVal _
strSPName As String, ByVal cmdCommand As SqlCommand) As Integer
'The purpose of this function is to execute a stored procedure with
'parameters as passed in with the command object The number of
'rows affected is returned
Try
Dim intRowsAffected As Integer
Dim sqlConn As New SqlClient.SqlConnection(strConnection)
Trang 21UnhandledExceptionHandler()
End Try
End Function
9. Next, create the spUpdateProducts stored procedure on the NorthwindSQL database,
using Visual Studio NET Server Explorer
CREATE PROCEDURE dbo.spUpdateProducts
UPDATE Products set ProductName = @ProductName, SupplierId =
@SupplierId, CategoryId = @CategoryId, QuantityPerUnit =
@QuantityPerUnit, UnitPrice = @UnitPrice, UnitsInStock =
@UnitsInStock, UnitsOnOrder = @UnitsOnOrder,
'The purpose of this function is to update data in the Suppliers
'table based on information in a DataSet that changed
'****************************************************************
Try
Dim oRow As DataRow
Dim intRowsAffected As Integer
For Each oRow In dsChangedDataSet.Tables("Results").Rows
Dim cmdCommand As New SqlClient.SqlCommand()
Trang 2211.Add the AddSuppliersInsertUpdateParameters procedure to clsDatabase.
Sub AddSuppliersInsertUpdateParameters(ByRef cmdCommand As _
SqlClient.SqlCommand, ByVal oRow As DataRow, ByVal _
blnAddSupplierId As Boolean)
'The purpose of this procedure is to add the parameters to the
'command object that will be passed to the stored procedure for
'updating or inserting Suppliers
Try
Dim sqlparm As New SqlClient.SqlParameter()
'If updating a record, then will need to specify the SupplierId 'If inserting, then one will not have been assigned yet (and
'thus the insert stored procedure doesn't expect it as a
Trang 2312.Next, create the spUpdateSuppliers stored procedure on the database.
CREATE PROCEDURE dbo.spUpdateSuppliers
Trang 24Dim clsDb As New clsDatabase()
clsDb.ProcessUpdates(CONN, PROD, dsSearchResults)
clsDb = Nothing
MsgBox("Save Completed If no other messages appeared " & _
"indicating any errors, then all changes were successful.")
The only difference in the two events is that the SUPP constant is passed as a parameter to
ProcessUpdates instead of the PROD constant This lets ProcessUpdates know whether the data
to be updated applies to Products or Suppliers This is another example of code that we could havemade totally generic and placed on the base form since it is almost exactly the same for both childforms However, since this references the clsDatabase.vb class module that isn't present in that baseforms project, we duplicated it here instead of adding the clsDatabase to the base forms project orreferencing it from that project You may have other ideas on how we could have avoided this
duplication; there are multiple ways that we could have done this
Next, we added the ProcessUpdates method within which the DataSet is analyzed to see if it hasany changes ProcessUpdates method acts as the processor for calling the appropriate methods toupdate data in the database
'Handle any changed records
If dsdata.HasChanges(DataRowState.Modified) Then
Dim dsChangedDataSet As DataSet
dsChangedDataSet = dsdata.GetChanges(DataRowState.Modified)
The first line of code above checks the HasChanges property of the DataSet with the optional
parameter DataRowState.Modified to determine if any changed records exist in the DataSet If they
do, then the GetChanges method is invoked to fill a new DataSet with only the records that changed
If dsChangedDataSet.HasErrors Then
HandleDataSetErrors(dsChangedDataSet)
Else
'Update the changes in the database
If strUpdateTable = "Products" Then
Dim ErrorRows() As DataRow
Dim oRow As DataRow
ErrorRows = GetAllErrors(dsChanged)
Trang 25'On each DataRow, examine the RowError property.
Dim i As Integer
Dim strError As String
strError = "The following errors occurred - "
Notice that an error number, -5000, is raised when the DataSet has errors That number can bereplaced with any appropriate error number and is just for demonstration purposes:
encountered, they are loaded into an array of DataRows
For Each myTable In rsChanges.Tables
'See if the table has errors If not, skip it
For Each oRow In dsChangedDataSet.Tables("Results").Rows
smallintDiscontinued = oRow("Discontinued")
'Format to the format that SQL Server expects
'The equivalent to Boolean in SQL Server is BIT
'A Bit can have 1 for True or 0 for False
'A Boolean in VB can have -1 for True or 0 for False
If smallintDiscontinued = vbYes Then
Trang 26Further notice that we have to re-format the Discontinued value before passing it to the database.The value in Visual Basic NET for a Boolean is different from than which SQL Server expects ATrue in Visual Basic NET is -1 while, in SQL Server, a bit (which is the equivalent to Boolean)value of True is +1.
Before the stored procedure can be run to actually update the changes to the Products / Suppliersrecords in the database, we must first add the parameters to the Command object to pass to SQL Server
to tell it which records to update We will place the code to add these parameters in a procedure calledAddProductsInsertUpdateParameters or AddProductsInsertUpdateParameters TheParameters.Add method is being used to assign the parameters that the stored procedure expects tothe corresponding values that came from the local DataSet If we are adding a record, the record willnot have a ProductId / SupplierId as one won't have been assigned yet In this case, the storedprocedure doesn't expect it for a parameter:
Next, we added the ExecuteSPWithParameters function to clsDatabase This is a genericfunction that will execute a stored procedure – with the parameters as passed with the Command object– and will return the number of rows affected We will be able to call this function in multiple places:
Dim intRowsAffected As Integer
Dim sqlConn As New SqlClient.SqlConnection(strConnection)
Trang 27Finally, we added the spUpdateProducts and spUpdateSuppliers stored procedures to theNorthwindSQL database These stored procedures accept all of the values in the Products or Supplierstable as parameters and then update the record for that ProductId or SupplierId with all of thevalues passed in:
CREATE PROCEDURE dbo.spUpdateProducts
UPDATE Products set ProductName = @ProductName, SupplierId =
@SupplierId, CategoryId = @CategoryId, QuantityPerUnit =
@QuantityPerUnit, UnitPrice = @UnitPrice, UnitsInStock =
@UnitsInStock, UnitsOnOrder = @UnitsOnOrder,
a record that another user has more recently changed
Handling Deleted Records
Now that we have added the code to our in-progress application to handle records that have changed,let's move on to handling records that have been deleted from the local DataSet
Try It Out – Removing Deleted Records in the DataSet from the Database
1. Add the following code in the ProcessUpdates procedure of clsDatabase immediatelyafter the section for handling changed records and just above the Catch statement, as shownbelow:
Trang 28DeleteRecordsInDb(strConnection, dsDeletedDataSet, _ strUpdateTable)
End If
End If
Catch
'Error handling goes here
2. Next, add the DeleteRecordsInDb procedure to clsDatabase
Sub DeleteRecordsInDb(ByVal strConnection As String, ByVal _
dsDeletedDataSet As DataSet, ByVal strTableName As String) '**************************************************************** 'The purpose of this function is to delete data in the Products 'table based on information in a DataSet that was deleted
'**************************************************************** Try
Dim oRow As DataRow
Dim intRowsAffected As Integer
For Each oRow In dsDeletedDataSet.Tables("Results").Rows Dim cmdCommand As New SqlClient.SqlCommand()
'Reject changes so it will allow access to the ProductId oRow.RejectChanges()
If strTableName = "Products" Then
AddDeleteParameters(cmdCommand, "@ProductId", _ oRow("ProductId"))
Trang 30For Each oRow In dsDeletedDataSet.Tables("Results").Rows
Dim cmdCommand As New SqlClient.SqlCommand()
'Reject changes so it will allow access to the ProductId
Trang 31We also added the AddDeleteParameters procedure to clsDatabase It will add a single
parameter to the Command object, which, in the case of both of our stored procedures, will be theirrespective Id's (ProductId or SupplierId) The name of the parameter is passed in using
strVarname, and intId designates which record gets deleted using the unique ProductId orSupplierId
Dim sqlparm As New SqlClient.SqlParameter()
sqlparm = cmdCommand.Parameters.Add(strVarName, SqlDbType.Int)
sqlparm.Value = intId
Finally, we created the stored procedures necessary to delete the specified record in either the Products
or Suppliers table The code below shows how the ProductId is used to specify which record is to bedeleted from the Products table
CREATE PROCEDURE dbo.spDeleteProducts
Handling Added Records
Now that we've handled updating existing records or deleting them, it's time to implement the code toadd new records to the database
Try It Out – Saving Added Records in the DataSet to the Database
1. Add the code below to the end of the ProcessUpdates procedure in clsDatabase abovethe Catch statement
'Handle any new records
'Update the database with the new records
If strUpdateTable = "Products" Then
InsertProductsInDb(strConnection, dsAddedDataSet)
ElseIf strUpdateTable = "Suppliers" Then
InsertSuppliersInDb(strConnection, dsAddedDataSet)
End If
'If the dsAddedDataSet was changed in the InsertXXXXInDb
'method (because a new ProductId or SupplierId was
Trang 32'auto-generated by the database), then will need to 'update the Id for each record that was added.
If dsAddedDataSet.HasChanges Then
Dim dsChangedAddedDataSet As DataSet
dsChangedAddedDataSet = _
dsAddedDataSet.GetChanges(DataRowState.Added) 'merge the dsChangedAddedDataSet with the
'dsSearchResults
dsdata.Merge(dsChangedAddedDataSet.GetChanges) dsdata.AcceptChanges()
'Get rid of the duplicates that got created on merge 'because the primary key wasn't set yet (i.e delete 'the records that have a ProductId = 0 that are now 'in duplicate of the ones with the newly assigned 'ProductId
Dim oRow As DataRow
For Each oRow In dsdata.Tables("results").Rows
If strUpdateTable = "Products" Then
2. Add the InsertProductsInDb procedure to clsDatabase.
Sub InsertProductsInDb(ByVal strConnection As String, ByVal _
dsInsertedDataSet As DataSet)
'**************************************************************** 'The purpose of this function is to insert data into the Products 'table based on information in a DataSet that changed
'**************************************************************** Try
Dim oRow As DataRow
Dim intRowsAffected As Integer
Dim SmallIntDiscontinued As Int16
For Each oRow In dsInsertedDataSet.Tables("Results").Rows Dim cmdCommand As New SqlClient.SqlCommand()
SmallIntDiscontinued = oRow("Discontinued")
Trang 33'Format to the format that SQL Server expects.
'The equivalent to Boolean in SQL Server is BIT
'A bit can have 1 for True or 0 for False
'A boolean in VB can have -1 for True or 0 for False
If SmallIntDiscontinued = vbYes Then
'Now need to retrieve the ProductId that was auto-generated
'by the database and include it in our DataSet
AddProductNameParameters(cmdCommand, oRow("ProductName"))
intRowsAffected = ExecuteSPWithParameters(strConnection, _
"spGetProductIdByProductName", cmdCommand)
'Retrieve the ProductId from the value returned by the
'stored procedure and put it into our DataSet
3. Add the spInsertProducts stored procedure to the database
CREATE PROCEDURE dbo.spInsertProducts
INSERT INTO Products (ProductName, SupplierId, CategoryId,
QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
ReorderLevel, Discontinued)
VALUES (@ProductName, @SupplierId, @CategoryId,
@QuantityPerUnit, @UnitPrice, @UnitsInStock, @UnitsOnOrder,
@ReorderLevel, @Discontinued)
RETURN
Trang 344. Next, add the AddProductNameParameters procedure to clsDatabase.
Sub AddProductNameParameters(ByRef cmdCommand As sqlclient.SqlCommand, _
ByVal strProductName As String)
'The purpose of this procedure is to add the parameters to the
'command object that will be passed to the stored procedure for
'retrieving the ProductId that was just assigned
5. On the SQL Server database, add the spGetProductIdByProductName stored procedure
CREATE PROCEDURE dbo.spGetProductIdByProductName
'The purpose of this function is to insert data into the Suppliers
'table based on information in a DataSet that changed
'****************************************************************
Try
Dim oRow As DataRow
Dim intRowsAffected As Integer