Pro VB 2005 and the .NET 2.0 Platform Second Edition phần 9 ppt

109 289 0
Pro VB 2005 and the .NET 2.0 Platform Second Edition phần 9 ppt

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

CHAPTER 24 ■ DATABASE ACCESS WITH ADO.NET824 ' Update Inventory Table with new row. Dim newCar As DataRow = dsCarInventory.Tables("Inventory").NewRow() newCar("CarID") = newCarID newCar("Make") = newCarMake newCar("Color") = newCarColor newCar("PetName") = newCarPetName dsCarInventory.Tables("Inventory").Rows.Add(newCar) Try dAdpater.Update(dsCarInventory.Tables("Inventory")) Catch Console.WriteLine("Sorry! Error! Canceling request") End Try End Sub Once you have created your command object, you plug it into the adapter via the InsertCommand property. Next, you add a new row to the Inventory DataTable maintained by the dsCarInventory object. Once you have added this DataRow back into the DataTable, the adapter will execute the SQL found within the InsertCommand property, given that the RowState of this new row is DataRowState.Added. Setting the UpdateCommand Property The modification of the UpdateCarPetName() method is more or less identical. Simply build a new command object and plug it into the UpdateCommand property. Private Sub UpdateCarPetName(ByVal dAdpater As SqlDataAdapter) Dim carToUpdate As Integer = 0 Dim newPetName As String = "" Console.Write("Enter CarID of car to modify: ") Try carToUpdate = Integer.Parse(Console.ReadLine()) Catch ex As FormatException Console.WriteLine(ex.Message) Return End Try Console.Write("Enter new pet name: ") newPetName = Console.ReadLine() Dim sql As String = _ String.Format("Update Inventory Set PetName = '{0}' Where CarID = '{1}'", _ newPetName, carToUpdate) Dim cmd As SqlCommand = New SqlCommand(sql, cnObj) dAdpater.UpdateCommand = cmd Dim carRowToUpdate As DataRow() = _ dsCarInventory.Tables("Inventory").Select(String.Format("CarID = '{0}'", _ carToUpdate)) carRowToUpdate(0)("PetName") = newPetName Try dAdpater.Update(dsCarInventory.Tables("Inventory")) Catch Console.WriteLine("Sorry! Error! Canceling request") End Try End Sub In this case, when you select a specific row (via the Select() method), the RowState value of said row is automatically set to DataRowState.Modified. The only other point of interest here is that the Select() method returns an array of DataRow objects; therefore, you must specify the exact row you wish to modify. 5785ch24.qxd 3/31/06 11:32 AM Page 824 CHAPTER 24 ■ DATABASE ACCESS WITH ADO.NET 825 Setting the DeleteCommand Property Last but not least, you have the following update to the DeleteCar() method: Private Sub DeleteCar(ByVal dAdpater As SqlDataAdapter) ' Get ID of car to delete, then do so. Dim sql As String = _ String.Format("Delete from Inventory where CarID = '{0}'", carToDelete) Dim cmd As SqlCommand = New SqlCommand(sql, cnObj) dAdpater.DeleteCommand = cmd Dim carRowToDelete As DataRow() = _ dsCarInventory.Tables("Inventory").Select(String.Format("CarID = '{0}'", _ carToDelete)) carRowToDelete(0).Delete() Try dAdpater.Update(dsCarInventory.Tables("Inventory")) Catch Console.WriteLine("Sorry! Error! Canceling request") End Try End Sub In this case, you find the row you wish to delete (again using the Select() method) and then set the RowState property to DataRowState.Deleted by calling Delete(). ■Source Code The CarsInvertoryUpdaterDS project is included under the Chapter 24 subdirectory. Autogenerating SQL Commands Using CommandBuilder Types You might agree that working with data adapters can entail a fair amount of code, given the need to build each of the four command objects and the associated connection string (or DbConnection- derived object). To help simplify matters, each of the ADO.NET data providers that ships with .NET 2.0 provides a command builder type. Using this type, you are able to automatically obtain command objects that contain the correct Insert, Delete, and Update command types based on the initial Select statement. The SqlCommandBuilder automatically generates the values contained within the SqlDataAdapter’s InsertCommand, UpdateCommand, and DeleteCommand properties based on the initial SelectCommand. Clearly, the benefit is that you have no need to build all the SqlCommand and SqlParameter types by hand. An obvious question at this point is how a command builder is able to build these SQL command objects on the fly. The short answer is metadata. At runtime, when you call the Update() method of a data adapter, the related command builder will read the database’s schema data to autogenerate the underlying insert, delete, and update command objects. Consider the following example, which deletes a row in a DataSet using the autogenerated SQL statements. Sub Main() Dim theCarsInventory As DataSet = New DataSet("CarsDS") ' Make connection. Dim cn As SqlConnection = _ New SqlConnection("server=(local);User ID=sa;Pwd=;database=Cars") 5785ch24.qxd 3/31/06 11:32 AM Page 825 CHAPTER 24 ■ DATABASE ACCESS WITH ADO.NET826 ' Autogenerate INSERT, UPDATE, and DELETE commands ' based on exiting SELECT command. Dim da As SqlDataAdapter = New SqlDataAdapter("SELECT * FROM Inventory", cn) Dim invBuilder As SqlCommandBuilder = New SqlCommandBuilder(da) ' Fill data set. da.Fill(theCarsInventory, "Inventory") PrintDataSet(theCarsInventory) ' Delete row based on user input and update database. Try Console.Write("Row # to delete: ") Dim rowToDelete As Integer = Integer.Parse(Console.ReadLine()) theCarsInventory.Tables("Inventory").Rows(rowToDelete).Delete() da.Update(theCarsInventory, "Inventory") Catch e As Exception Console.WriteLine(e.Message) End Try ' Refill and reprint Inventory table. theCarsInventory = New DataSet() da.Fill(theCarsInventory, "Inventory") PrintDataSet(theCarsInventory) End Sub In the previous code, notice that you made no use of the command builder object (SqlCommandBuilder in this case) beyond passing in the data adapter object as a constructor parameter. As odd as this may seem, this is all you are required to do (at a minimum). Under the hood, this type will configure the data adapter with the remaining command objects. Now, while you may love the idea of getting something for nothing, do understand that com- mand builders come with some critical restrictions. Specifically, a command builder is only able to autogenerate SQL commands for use by a data adapter if all of the following conditions are true: • The Select command interacts with only a single table (e.g., no joins). • The single table has been attributed with a primary key. • The column(s) representing the primary key is accounted for in your SQL Select statement. If these restrictions are unacceptable, rest assured that much of the ADO.NET “grunge” code will be autogenerated by the Visual Studio 2005 Windows Forms and ASP.NET designer surfaces and integrated wizards. You’ll see the Windows Forms ADO.NET wizards in action at the conclusion of this chapter (and their ASP.NET counterparts in Part 7). ■Source Code The MySqlCommandBuilder project is found under the Chapter 24 subdirectory. Multitabled DataSets and DataRelation Objects Currently, all of this chapter’s examples involved DataSets that contained a single DataTable object. However, the power of the disconnected layer really comes to light when a DataSet object contains numerous interrelated DataTables. In this case, you are able to insert any number of DataRelation objects into the DataSet’s DataRelation collection to account for the interdependencies of the tables. Using these objects, the client tier is able to navigate between the table data without incurring network round-trips. 5785ch24.qxd 3/31/06 11:32 AM Page 826 CHAPTER 24 ■ DATABASE ACCESS WITH ADO.NET 827 Figure 24-17. Viewing related DataTables To illustrate the use of data relation objects, create a new Windows Forms project called Multi- tabledDataSet. The GUI is simple enough. In Figure 24-17 you can see three DataGridView widgets that hold the data retrieved from the Inventory, Orders, and Customers tables of the Cars database. In addition, the single Button pushes any and all changes back to the data store. To keep things simple, the MainForm will make use of command builders to autogenerate the SQL commands for each of the three SqlDataAdapters (one for each table). Here is the initial update to the Form-derived type: Public Class MainForm ' Formwide DataSet. Private carsDS As DataSet = New DataSet("CarsDataSet") ' Make use of command builders to simplify data adapter configuration. Private sqlCBInventory As SqlCommandBuilder Private sqlCBCustomers As SqlCommandBuilder Private sqlCBOrders As SqlCommandBuilder ' Our data adapters (for each table). Private invTableAdapter As SqlDataAdapter Private custTableAdapter As SqlDataAdapter Private ordersTableAdapter As SqlDataAdapter ' Formwide connection object. Private cn As SqlConnection = _ New SqlConnection("server=(local);uid=sa;pwd=;database=Cars") End Class 5785ch24.qxd 3/31/06 11:32 AM Page 827 CHAPTER 24 ■ DATABASE ACCESS WITH ADO.NET828 The Form’s constructor does the grunge work of creating your data-centric member variables and filling the DataSet. Also note that there is a call to a private helper function, BuildTableRelationship(), as shown here: Sub New() ' This call is required by the Windows Forms designer. InitializeComponent() CenterToScreen() ' Create adapters. invTableAdapter = New SqlDataAdapter("Select * from Inventory", cn) custTableAdapter = New SqlDataAdapter("Select * from Customers", cn) ordersTableAdapter = New SqlDataAdapter("Select * from Orders", cn) ' Autogenerate commands. sqlCBInventory = New SqlCommandBuilder(invTableAdapter) sqlCBOrders = New SqlCommandBuilder(ordersTableAdapter) sqlCBCustomers = New SqlCommandBuilder(custTableAdapter) ' Add tables to DS. invTableAdapter.Fill(carsDS, "Inventory") custTableAdapter.Fill(carsDS, "Customers") ordersTableAdapter.Fill(carsDS, "Orders") ' Build relations between tables. BuildTableRelationship() ' Bind to grids dataGridViewInventory.DataSource = carsDS.Tables("Inventory") dataGridViewCustomers.DataSource = carsDS.Tables("Customers") dataGridViewOrders.DataSource = carsDS.Tables("Orders") End Sub The BuildTableRelationship() helper function does just what you would expect. Recall that the Cars database expresses a number of parent/child relationships, accounted for with the following code: Private Sub BuildTableRelationship() ' Create CustomerOrder data relation object. Dim dr As DataRelation = New DataRelation("CustomerOrder", _ carsDS.Tables("Customers").Columns("CustID"), _ carsDS.Tables("Orders").Columns("CustID")) _ carsDS.Relations.Add(dr) ' Create InventoryOrder data relation object. dr = New DataRelation("InventoryOrder", _ carsDS.Tables("Inventory").Columns("CarID"), _ carsDS.Tables("Orders").Columns("CarID")) _ carsDS.Relations.Add(dr) End Sub Now that the DataSet has been filled and disconnected from the data source, you can manipulate each table locally. To do so, simply insert, update, or delete values from any of the three DataGridViews. When you are ready to submit the data back for processing, click the Form’s Update button. The code behind the Click event should be clear at this point: Private Sub btnUpdate_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnUpdate.Click 5785ch24.qxd 3/31/06 11:32 AM Page 828 CHAPTER 24 ■ DATABASE ACCESS WITH ADO.NET 829 Try invTableAdapter.Update(carsDS, "Inventory") custTableAdapter.Update(carsDS, "Customers") ordersTableAdapter.Update(carsDS, "Orders") Catch ex As Exception MessageBox.Show(ex.Message) End Try End Sub Once you update, you will find that each table in the Cars database has been correctly altered. Navigating Between Related Tables To illustrate how a DataRelation allows you to move between related tables programmatically, extend your GUI to include a new Button type and a related TextBox. The end user is able to enter the ID of a customer and obtain all the information about that customer’s order, which is placed in a simple message box. The Button’s Click event handler is implemented as follows: Private Sub btnGetInfo_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnGetInfo.Click Dim strInfo As String = "" Dim drCust As DataRow = Nothing Dim drsOrder As DataRow() = Nothing ' Get the specified CustID from the TextBox. Dim theCust As Integer = Integer.Parse(Me.txtCustID.Text) ' Now based on CustID, get the correct row in Customers table. drCust = carsDS.Tables("Customers").Rows(theCust) strInfo &= "Cust #" & drCust("CustID").ToString() & "" & Chr(10) & "" ' Navigate from customer table to order table. drsOrder = drCust.GetChildRows(carsDS.Relations("CustomerOrder")) ' Get order number. For Each r As DataRow In drsOrder strInfo &= "Order Number: " & r("OrderID").ToString() & "" & Chr(10) & "" Next ' Now navigate from order table to inventory table. Dim drsInv As DataRow() = _ drsOrder(0).GetParentRows(carsDS.Relations("InventoryOrder")) ' Get Car info. For Each r As DataRow In drsInv strInfo &= "Make: " & r("Make").ToString() & "" & Chr(10) & "" strInfo &= "Color: " & r("Color").ToString() & "" & Chr(10) & "" strInfo &= "Pet Name: " & r("PetName").ToString() & "" & Chr(10) & "" Next MessageBox.Show(strInfo, "Info based on cust ID") End Sub As you can see, the key to moving between data tables is to use a handful of methods defined by the DataRow type. Let’s break this code down step by step. First, you obtain the correct customer ID from the text box and use it to grab the correct row in the Customers table (using the Rows property, of course). Next, you navigate from the Customers table to the Orders table, using the CustomerOrder data relation. Notice that the DataRow.GetChildRows() method allows you to grab rows from your child table. Once you do, you can read information out of the table. Your final step is to navigate from the Orders table to its parent table (Inventory) using the GetParentRows() method. At this point, you can read information from the Inventory table using the Make, PetName, and Color columns. Figure 24-18 shows one possible output. 5785ch24.qxd 3/31/06 11:32 AM Page 829 CHAPTER 24 ■ DATABASE ACCESS WITH ADO.NET830 Hopefully, this last example has you convinced of the usefulness of the DataSet type. Given that a DataSet is completely disconnected from the underlying data source, you can work with an in- memory copy of data and navigate around each table to make any necessary updates, deletes, or inserts. Once you’ve finished, you can then submit your changes to the data store for processing. ■Source Code The MultitabledDataSetApp project is included under the Chapter 24 subdirectory. We’re Off to See the (Data) Wizard At this point in the chapter, you have seen numerous ways to interact with the types of ADO.NET in a “wizard-free” manner. While it is (most definitely) true that understanding the ins and outs of work- ing with your data provider is quite important, it is also true that this can lead to hand cramps from typing the large amount of boilerplate code. To wrap things up, therefore, I’d like to point out a few data-centric wizards you may wish to make use of when buildingWindows Forms applications. Be aware that space does not allow me to comment on all of the UI-centric data wizards pro- vided by Visual Studio 2005, but to illustrate the basics, let’s examine some additional configuration options of the DataGridView widget. Assume you have created a new Windows Forms application (named EasyDataAccessForm) that has a single Form containing a DataGridView control named inventoryDataGridView. Using the designer, activate the inline editor for this widget, and from the Choose Data Source drop-down listbox, click the Add Project Data Source link (see Figure 24-19). This will launch the Data Source Configuration Wizard. On the first step, simply select the Database icon and click Next. On the second step, click New Connection and establish a connection to the Cars database (using the same set of steps described earlier in this chapter within the “Connect- ing to the Cars Database from Visual Studio 2005” section). The third step allows you to inform the wizard to store the connection string within an external app.config file (which is generally a good idea) within a properly configured <connectionStrings> element. As the final step, you are able to select which database objects you wish to account for within the generated DataSet, which for your purposes here will simply be the Inventory table, as shown in Figure 24-20. Figure 24-18. Navigating data relations 5785ch24.qxd 3/31/06 11:32 AM Page 830 CHAPTER 24 ■ DATABASE ACCESS WITH ADO.NET 831 Once you complete the wizard, you will notice that the DataGridView automatically displays the column names within the designer. In fact, if you run your application as is, you will find the contents of the Inventory table displayed within the grid’s UI! As you might be suspecting, this wizard updated your Form with numerous lines of code; however, if you examine the code behind the Forms designer, you find little else than the following implementation of the Form’s Load event: Figure 24-19. Adding a data source Figure 24-20. Selecting the Inventory table 5785ch24.qxd 3/31/06 11:32 AM Page 831 Public Class MainForm Private Sub MainForm_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load 'TODO: This line of code loads data into the 'CarsDataSet.Inventory' table. 'You can move, or remove it, as needed. Me.InventoryTableAdapter.Fill(Me.CarsDataSet.Inventory) End Sub End Class To understand what this code is in fact doing, you need to first understand the role of strongly typed DataSet objects. Strongly Typed DataSets Strongly typed DataSets (as the name implies) allow you to interact with a DataSet’s internal tables using database-specific properties, methods, and events, rather than via the generalized Tables property. If you activate the View ➤ Class View menu option of Visual Studio 2005, you will find that the wizard has created a new type deriving from DataSet named CarsDataSet. As you can see in Figure 24-21, this class type defines a number of members that allow you to select, modify, and update its contents. CHAPTER 24 ■ DATABASE ACCESS WITH ADO.NET832 Figure 24-21. The strongly typed DataSet Once the wizard completes its task, it places a member variable of type CarDataSet within your Form’s *.Designer.vb file (which is the same member variable manipulated in the Load event of your Form): Partial Class MainForm Inherits System.Windows.Forms.Form Friend WithEvents CarsDataSet As EasyDataAccessForm.CarsDataSet End Class 5785ch24.qxd 3/31/06 11:32 AM Page 832 The Autogenerated Data Component In addition to the strongly typed DataSet, the wizard generated a data component (named InventoryTableAdapter in this example) that encapsulates the underlying data connection, data adapter, and command objects used to interact with the Inventory table, as you see in Figure 24-22. CHAPTER 24 ■ DATABASE ACCESS WITH ADO.NET 833 Figure 24-22. The autogenerated table adapter data component As well, this component defines custom Fill() and Update() methods that are tailor-made to operate on your CarsDataSet, in addition to a set of members used to insert, update, or delete row data from the internal Inventory table. I’ll leave it up to interested readers to dive into the implemen- tation details of each member. The good news is that after all your work in this chapter, the code behind each member should look quite familiar. ■Source Code The EasyDataAccessForm project is included under the Chapter 24 subdirectory. ■Note If you are interested in taking a deeper look at the ADO.NET object model, including the numerous Visual Studio 2005 designers, check out Pro ADO.NET 2.0 by Sahil Malik (Apress, 2005). Summary ADO.NET is a new data access technology developed with the disconnected n-tier application firmly in mind. The System.Data namespace contains most of the core types you need to program- matically interact with rows, columns, tables, and views. As you have seen, the .NET platform ships with numerous data providers that allow you to leverage the connected and disconnected layers of ADO.NET. 5785ch24.qxd 3/31/06 11:32 AM Page 833 [...]... Studio 2005 has full-blown IntelliSense support for *.aspx files, and allows you to drag and drop UI elements directly from the Toolbox into the HTML document! Using the Visual Studio 2005 Toolbox, select the Standard tab and drag and drop a Button, Label, and GridView control onto the page designer (the GridView widget can be found under the Data tab of the Toolbox) Feel free to make use of the Properties... author the HTML!) Beyond this major benefit, ASP NET web controls support a Windows Forms–like programming model, given that the names of the properties, methods, and events mimic their Windows Forms equivalents To illustrate, handle the Click event for the Button type using either the Visual Studio Properties window (via the lightning-bolt icon) or using the drop-down boxes mounted at the top of the. .. using classic ADO and returns the rows as a generic HTML table 847 5785ch25.qxd 848 3/31/06 11: 39 AM Page 848 CHAPTER 25 ■ BUILDING ASP.NET 2.0 WEB PAGES For this example, the ASP page uses the intrinsic ASP Request COM object to read the values of the incoming form data (appended to the query string) and echo them back to the caller (not terribly exciting, but it illustrates the point of the request/response... 3/31/06 11: 39 AM Page 851 CHAPTER 25 ■ BUILDING ASP.NET 2.0 WEB PAGES • ASP.NET 2.0 supports themes, which offer a declarative manner to change the look and feel of the entire web application • ASP.NET 2.0 supports web parts, which can be used to allow end users to customize the look and feel of a web page • ASP.NET 2.0 supports a web-based configuration and management utility that maintains your web.config... tables and any number of optional interrelationships, constraints, and expressions The beauty of establishing relations on your local tables is that you are able to programmatically navigate between them while disconnected from the remote data store You also examined the role of the data adapter in this chapter Using this type (and the related SelectCommand, InsertCommand, UpdateCommand, and DeleteCommand... DeleteCommand properties), the adapter can resolve changes in the DataSet with the original data store Also, you learned about the connected layer of ADO.NET and came to understand the role of data reader types 5785ch25.qxd 3/31/06 11: 39 AM PART Page 835 7 ■■■ Web Applications and XML Web Services 5785ch25.qxd 3/31/06 11: 39 AM Page 836 5785ch25.qxd 3/31/06 11: 39 AM CHAPTER Page 837 25 ■■■ Building ASP.NET 2.0. .. port 80) and sends the HTTP request for the default page at the http://www.IntertechTraining.com website, at which point the browser displays the site’s default page Once the user posts back to the web server, it is then able to process the incoming HTTP request and may scrape out any client-supplied input values (such as values within a text box) in order to format a proper HTTP response Web programmers... NET 2.0 In fact, it is perfectly fine to have a single IIS installation host NET 1.x and NET 2.0 based web content Major Enhancements of ASP.NET 2.0 ASP NET 2.0 provides a number of new namespaces, types, utilities, and technologies to the NET web development landscape Consider this partial list: • As you have seen, ASP.NET 2.0 no longer requires websites to be hosted under IIS during the testing and. .. as shown in Figure 25-4 Figure 25-4 The HTML tab of the Toolbox Building an HTML-based User Interface Before you add the HTML widgets to the HTML , it is worth pointing out that Visual Studio 2005 allows you to edit the overall look and feel of the *.htm file itself using the integrated HTML designer and the Properties window If you select DOCUMENT from the Properties window, as shown in Figure... able to configure various aspects of the HTML page, such as the background color Figure 25-5 Editing an HTML document via the VS 2005 Properties window 843 5785ch25.qxd 844 3/31/06 11: 39 AM Page 844 CHAPTER 25 ■ BUILDING ASP.NET 2.0 WEB PAGES Update the of the default.htm file to display some literal text that prompts the user to enter a user name and password, and choose a background color of your . Visual Studio 20 05 designers, check out Pro ADO .NET 2. 0 by Sahil Malik (Apress, 20 05) . Summary ADO .NET is a new data access technology developed with the disconnected n-tier application firmly in mind. The. 3/31 /06 11: 39 AM Page 8 40 CHAPTER 25 ■ BUILDING ASP .NET 2. 0 WEB PAGES 841 Many of the examples in this chapter and the next will make use of WebDev.WebServer.exe via Visual Studio 20 05, rather. the Inventory table, as shown in Figure 24 - 20 . Figure 24 -18. Navigating data relations 5785ch24.qxd 3/31 /06 11: 32 AM Page 8 30 CHAPTER 24 ■ DATABASE ACCESS WITH ADO .NET 831 Once you complete the

Ngày đăng: 12/08/2014, 23:21

Tài liệu cùng người dùng

Tài liệu liên quan