Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 53 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
53
Dung lượng
596,24 KB
Nội dung
How It Works The configuration and formatting of the controls in this example hardly needs much comment — the procedure was nearly identical to that used in list views in the preceding section. It is, however, worth scrutinizing the result in a little more detail. First, note the field specification for the DetailsView control: <asp:DetailsView > <Fields> <asp:BoundField DataField=”Species” HeaderText=”Species” SortExpression=”Species” /> <asp:BoundField DataField=”Description” HeaderText=”Description” SortExpression=”Description” /> <asp:CheckBoxField DataField=”Immortal” HeaderText=”Immortal” SortExpression=”Immortal” /> <asp:CommandField ShowDeleteButton=”True” ShowEditButton=”True” ShowInsertButton=”True” /> </Fields> </asp:DetailsView> The code used here is similar indeed to the column specification for the GridView control. As with that control, it isn’t necessary to specify template details for editing items — the controls required are instead inferred from the controls used in the field specification section. In addition, you can see where the com- mand buttons are specified, in the CommandField control. You can change the text displayed for these commands (or use images instead) by modifying this specification. Also, examine the code in the templates specified for the FormView control — for example, EditItemTemplate: <EditItemTemplate> Species: <asp:TextBox ID=”SpeciesTextBox” runat=”server” Text=’<%# Bind(“Species”) %>’> </asp:TextBox><br /> Description: <asp:TextBox ID=”DescriptionTextBox” runat=”server” Text=’<%# Bind(“Description”) %>’> </asp:TextBox><br /> Immortal: <asp:CheckBox ID=”ImmortalCheckBox” runat=”server” Checked=’<%# Bind(“Immortal”) %>’ /><br /> <asp:LinkButton ID=”UpdateButton” runat=”server” CausesValidation=”True” CommandName=”Update” Text=”Update”> </asp:LinkButton> <asp:LinkButton ID=”UpdateCancelButton” runat=”server” CausesValidation=”False” CommandName=”Cancel” Text=”Cancel”> </asp:LinkButton> </EditItemTemplate> This also looks familiar — the code is almost identical to that used in the analogous DataList control template used in the previous Try It Out — apart from a few minor cosmetic differences. 186 Chapter 5 44063c05.qxd:WroxBeg 9/12/06 10:36 PM Page 186 The other thing you did in this example was handle the ItemInserting event for both detail view con- trols. This provides for the GUID primary key field in the Species table, which must be generated from code — as you saw in the chapters on Windows data binding. The ItemInserting event fires when the user clicks the Update button but before data is added to the database. In both cases, simple code was used to generate a primary key GUID value: e.Values.Add(“SpeciesId”, Guid.NewGuid()); Both the DetailsViewInsertEventArgs and FormViewInsertEventArgs argument types allow you to do this by exposing the about-to-be-added item though a Values property that is a dictionary collec- tion of name/value pairs. Master/Detail Views The last topic to cover in this chapter is how to deal with master/detail views — an extremely common scenario that uses a list view and a detail view in combination. Selecting an item in the list view causes it to be displayed in the detail view, where it can be edited. In this situation, you don’t need pagination functionality in the detail view because the list view fulfils that purpose. The data-binding framework in ASP.NET has been designed with this situation in mind and makes it surprisingly easy to implement. In fact, you’ve seen pretty much everything that you need to do to implement this. However, in the Try It Out that follows, a few tips and tricks are introduced to stream- line matters. Try It Out Master/Detail Views 1. Copy the C:\BegVC#Databases\Chapter05\Ex0503 - Modifying List Data example directory from the earlier Try It Out to a new directory, C:\BegVC#Databases\Chapter05\ Ex0505 - Master-Detail View . 2. Open Visual Web Developer Express. 3. Select the File ➪ Open Web Site menu item and open the web site C:\BegVC#Databases\ Chapter05\Ex0505 - Master-Detail View . 4. Remove the DataList control from Default.aspx. 5. Remove all the code behind from Default.aspx.cs that you added in the earlier Try It Out example except the code for addButton_Click. In this event handler, remove the following line of code: DataList1.DataBind(); 6. In the Source view for Default.aspx, modify the column specification for the GridView con- trol as follows: <Columns> <asp:TemplateField HeaderText=”Species” SortExpression=”Species”> <ItemTemplate> 187 Databases and the Internet 44063c05.qxd:WroxBeg 9/12/06 10:36 PM Page 187 <asp:LinkButton ID=”speciesLabel” runat=”server” Text=’<%# Bind(“Species”) %>’ CommandName=”Select” /> </ItemTemplate> </asp:TemplateField> </Columns> 7. Refresh the schema for SqlDataSource1 as in earlier examples, and then add a new SqlDataSource control to the page after the existing SqlDataSource1 control. 8. For the new data source, use the existing FolktaleDBConnectionString, and configure the select command to obtain all columns from the Species table. 9. Add the following where clause specification: 10. Choose to generate data modification SQL statements for the data source. 11. Complete the Data Source Configuration Wizard. 12. Add a DetailsView control to the page and select the SqlDataSource2 data source. 13. Remove the SpeciesId field from the DetailsView control. 14. Auto-format the control using Classic scheme, and enable editing and deleting. 15. Add event handlers for the ItemDeleted and ItemUpdated events for the DetailsView con- trol with code as follows: protected void DetailsView1_ItemDeleted(object sender, DetailsViewDeletedEventArgs e) { GridView1.DataBind(); } protected void DetailsView1_ItemUpdated(object sender, DetailsViewUpdatedEventArgs e) { GridView1.DataBind(); } 16. In the Source view for Default.aspx, wrap the controls in the following HTML: </asp:SqlDataSource> <hr /> <div style=”float: left;”> <asp:GridView > </asp:GridView> </div> <div> Column SpeciesId Operator = Source Control Control ID GridView1 188 Chapter 5 44063c05.qxd:WroxBeg 9/12/06 10:36 PM Page 188 <asp:DetailsView > </asp:DetailsView> </div> <br style=”clear: left;”/> <hr /> <asp:LinkButton ID=”addButton” runat=”server” OnClick=”addButton_Click”>Add Species</asp:LinkButton> <br /> </div> </form> </body> </html> 17. Execute the application, and note that items selected in the master control are displayed in the detail view and can be modified there. Figure 5-24 shows the application in action. Figure 5-24: Master/detail view How It Works In this example you have used the data source from earlier in the chapter along with a second, filtered data source to create a master/detail view. You started by clearing out an old control and its associated code behind, including a reference to the control in the code for the Add Species button. Next you refor- matted the GridView control to show a single row from the Species table — the title field also called Species. In doing so you used a new type of bound column specification: TemplateField. The TemplateField column specification allows you to override the default layout of columns in a GridView control and provide the HTML to use for a column using familiar templates. You can use ItemTemplate, EditItemTemplate, and InsertItemTemplate templates in this control, as well as 189 Databases and the Internet 44063c05.qxd:WroxBeg 9/12/06 10:36 PM Page 189 HeaderTemplate and FooterTemplate, if desired. You use this control in this example to remove the necessity of having a second column whose only function is to supply a link button to select items. Instead, the Species field is rendered as the text of a link button and allows the user to select items by clicking their title: <asp:TemplateField HeaderText=”Species” SortExpression=”Species”> <ItemTemplate> <asp:LinkButton ID=”speciesLabel” runat=”server” Text=’<%# Bind(“Species”) %>’ CommandName=”Select” /> </ItemTemplate> </asp:TemplateField> Next, you added a second SqlDataSource control. It uses an advanced filter mechanism, as described earlier in the chapter, to choose items according to the selected item in another control — namely, the ListView control. ASP.NET makes this easy — you simply specify the ID of the control to use for filtering and the field to filter by, and it connects everything up without your having to worry about it any further. The new data source control returns only a single result, filtered according to the SpeciesId field. This could be extended to filter-related data. A table using SpeciesId as a foreign key, such as Character, could be filtered using the same master selection control. This would result in a filtered set of results, which might number more that one, which you could then page through and navigate using techniques already encountered in this chapter. One further modification was necessary (apart from the cosmetic changes) — the ItemDeleted and ItemUpdated events for the DetailsView control were handled. That’s necessary because changing the underlying data will cause the master list view to go out of date unless you manually refresh it by call- ing its DataBind() method: GridView1.DataBind(); With this in place, the master/detail view is complete — with a minimum of effort, and just a few tweaks required to get everything working properly. In general, remember the following when creating master/detail views: ❑ Use two data sources, where one is filtered by the master view. ❑ The detail view may not appear if no data is available after filtering, so controls making up this control may not always be visible, which can affect layout and functionality. ❑ When data changes are made, both data sources need refreshing. Summary In this chapter, you extended your knowledge of data-binding techniques to cover web applications. You saw how things differ from Windows applications, but also how many of the techniques used are similar or analogous to those required to implement data binding in Windows applications. You were introduced to all of the controls in ASP.NET that are responsible for data binding — both those that work as data sources and those that display data — and saw how they interrelate. You also put theory 190 Chapter 5 44063c05.qxd:WroxBeg 9/12/06 10:36 PM Page 190 into practice and saw these controls in action, and you learned a few helpful tips and tricks along the way. Specifically, you learned: ❑ How web and Windows applications differ. You saw that there are many similarities, especially when dealing with data access, but also some major differences. For example, Windows applica- tions are typically used by only one person at a time, while web applications may have to deal with thousands of simultaneous users. ❑ How to configure SQL Server 2005 Express for remote connections by enabling the named pipes protocol (and/or the TCP/IP protocol). ❑ How to configure connections in web applications — including remote connections. ❑ How the SqlDataSource control is used for data access, and how to configure it to connect to your data. ❑ How to sort, filter, and update data using a SqlDataSource. You saw how parameters can be used by SqlDataSource controls and how these parameters can be obtained from a number of sources. You can, for example, use querystring parameters from URLs, values stored in session state, and so on. ❑ What the data-bound controls in ASP.NET are and key features about them. ❑ How to use the data-bound controls to display list and detail data. You saw how the GridView and DataList controls can be configured to display data exposed by a SqlDataSource control, and you customized the display by changing the columns shown and the schemes used for HTML rendering. ❑ How to get around an ASP.NET problem that makes dealing with GUID data more difficult than it need be, noting how the parameters used by data source controls fail to recognize the GUID data type, and instead use object. By removing this type specification, you avoid data update errors. ❑ How to edit data in list and detail views by using the other templates that are included in the data-bound controls. ❑ How to visualize and edit data in master/detail relationships. You used a combination of a GridView and a DetailsView control to implement this scheme, and saw why it is necessary to use a second, filtered data source for the detail view. The next chapter delves deeper into the realm of ADO.NET and you learn to perform data access programmatically. Exercises 1. Which of the following are valid reasons to use remote database connections in ASP.NET rather than local database files? a. Security b. Convenience c. Performance 191 Databases and the Internet 44063c05.qxd:WroxBeg 9/12/06 10:36 PM Page 191 d. Data caching e. Flexibility f. Functionality 2. How would you configure a data source filter to remember filter settings for a user between sessions? 3. Which of the following data-bound controls are available in ASP.NET? a. Repeater b. DataGrid c. DataView d. DataList e. ItemView f. FormView g. DetailsForm 4. Copy the project C:\BegVC#Databases\Chapter05\Ex0505 - Master-Detail View to a new project, C:\BegVC#Databases\Chapter05\Q0504 - List Filtering. Modify this proj- ect by replacing the DetailsView control with a DataList control that displays entries from the Character table filtered by the existing GridView control. Display data in a three-column horizontal table layout and use the Classic auto-format scheme. None of the GUID data in the Character table should be displayed. The width of each item should be 200 pixels. Figure 5-25 shows the expected result. Figure 5-25: Exercise 4 goal 192 Chapter 5 44063c05.qxd:WroxBeg 9/12/06 10:36 PM Page 192 6 Accessing Databases Programmatically As you have seen throughout this book, ADO.NET is the technology used to access databases. Until now, however, you’ve almost exclusively used declarative data-binding techniques to access data — using controls and wizards to do a lot of the hard work for you rather than coding data- base access by hand. However, data binding often doesn’t give you quite the degree of control that you need in your applications, or might not do things as efficiently as you like. Also, data binding is geared toward applications with a visual interface, which doesn’t include many application types, such as Windows services. Or you might want to provide a completely custom-built user interface that doesn’t use the data-bound controls you’ve encountered in this book. In any of these circumstances you can use the ADO.NET classes independently of other database access techniques. From your code you can make connections, execute SQL statements, manage database objects, and manipulate data — all without any data binding whatsoever. The downside is that you have to remember to do everything properly, without missing important steps, and often without the help of wizards. The upside is that you obtain an almost limitless flexibility to make your applications work exactly the way you want them to, without having to deal with some of the quirks of data-bound controls. In this chapter you look at how you can achieve this flexibility. You learn to: ❑ Configure and use ADO.NET database connections ❑ Execute commands through a database connection ❑ Read data with data readers ❑ Use data adapters to exchange data with a database ❑ Use DataSet and DataTable objects For the most part, in this chapter you experiment with code in console applications. The techniques you learn will apply equally to web and Windows applications, but by using console applications 44063c06.qxd:WroxBeg 9/12/06 3:52 PM Page 193 there’s less extraneous code, so the database access code is clearer. The ADO.NET classes that enable you to access databases, as well as the relationships between these classes, were introduced in Chapter 2. In this chapter, you formalize that information and learn to manipulate these classes in your C# code. Database Connections The first step in accessing databases programmatically is to configure a connection object. Then you can execute commands against it, obtain data readers, exchange data with a data set using data adapters, and otherwise manipulate database data. As you have seen in previous chapters, the ADO.NET class used to connect to databases is SqlConnection. In this section you learn to create, configure, and use instances of this class, and explore connection pooling in the .NET Framework. Creating Connections SqlConnection objects are simple to use, and can be instantiated in the usual way: SqlConnection conn = new SqlConnection(); Once instantiated, you can configure the connection with a connection string using the SqlConnection.ConnectionString property: conn.ConnectionString = “<connection string>“; Alternatively, you can combine these steps into one by using a constructor: SqlConnection conn = new SqlConnection(“<connection string>“); In both these code fragments, “<connection string>” is the connection string used to connect to the database. As you saw in Chapter 3, connection strings consist of properties in the form of name/value combinations that define the connection. Those properties include the DBMS to connect to, the name of the database (or database file location), and security information. Rather than writing connection strings manually, you can use the Database Connection window that you’ve seen in previous chapters, which means that you can use the connection configuration wizard. Once you have done so, you can see the connection string in the properties for the connection, as shown in Figure 6-1. Figure 6-1: Obtaining connection strings from database connections 194 Chapter 6 44063c06.qxd:WroxBeg 9/12/06 3:52 PM Page 194 You cannot edit the connection string via the Properties window, but you can select the text displayed and copy it to your application. You can modify the connection string manually or by using the Modify Connection command to reconfigure the connection using the standard wizard. You can access this com- mand by right-clicking on the connection in the Database Explorer. This technique has another advantage — it means that you can edit the database through the Database Explorer window, making use of standard visual techniques to do so, without having to rely on code. Once you have a connection string, either created by hand or using the Database Connection window, you have to decide where to store it. There is nothing to stop you from hard-coding the string in your application wherever it is required by your code, but that isn’t an ideal solution — the string may be used multiple times, so changing it would mean changing it wherever it appears. Alternatively, you can use a variable or constant to define the connection string, centralizing it. That’s an improvement, but still requires a recompile to change the connection string if it needs changing. You can also use external stor- age, such as registry settings or a data file. One frequently used way, which you examine in more detail in a moment, is to use an application configuration file ( app.config in Windows/console applications or web.config for web applications). Using a configuration file means that no recompiling is necessary to change the string, and you can change it either in a text editor or programmatically without much effort. However, it does mean that you are exposing the connection string in plain text format, which may be an issue in some security-critical uses (especially if username and password information is stored in the connection string). Typically, con- figuration files are the best option. The final choice of which method to use, however, is up to you. In a configuration file, connection strings can be stored wherever you like, but there is a location that’s already configured for this purpose — the <connectionStrings> element. It is a child element of the root <configuration> element, and contains a number of <add> elements defining connection strings. The following code is an example of a configuration file for a Windows or console application with a connection string in place: <?xml version=”1.0” encoding=”utf-8” ?> <configuration> <connectionStrings> <add name=”MyConnectionString” connectionString=” Data Source=.\SQLEXPRESS; AttachDbFilename=C:\BegVC#Databases\FolktaleDB.mdf; Integrated Security=True; Connect Timeout=30; User Instance=True”/> </connectionStrings> </configuration> To access this information from your code, use the System.Configuration.ConfigurationManager class, which is included in the System.Configuration.dll library (not included by default to console applications). The preceding connection string could be accessed as follows: SqlConnection conn = new SqlConnection( ConfigurationManager.ConnectionStrings[“MyConnectionString”].ConnectionString); With this code in place, changes to connection strings stored in the application configuration file will automatically be utilized in your code. 195 Accessing Databases Programmatically 44063c06.qxd:WroxBeg 9/12/06 3:52 PM Page 195 [...]... 44063c06.qxd:WroxBeg 9/12/06 3 :52 PM Page 2 15 Accessing Databases Programmatically In the following Try It Out, you use the SqlCommandBuilder class to generate commands Try It Out Generating Commands 1 Copy the project C:\BegVC #Databases\ Chapter06\Ex0602 - Data Readers to a new project, C:\BegVC #Databases\ Chapter06\Ex0603 - Generating Commands (Copy and rename the directory, open it in Visual C# Express, and rename... StateChangeEventArgs e) { Console.WriteLine(“Connection state changed from {0} to {1}.”, e.OriginalState, e.CurrentState); } 2 15 44063c06.qxd:WroxBeg 9/12/06 3 :52 PM Page 216 Chapter 6 4 5 Execute the application The result is shown in Figure 6 -5 Close the application and Visual C# Express Figure 6 -5: Generated command output How It Works In this example, a SqlCommandBuilder object generates delete, insert, and... the following Try It Out, you use a data reader to obtain table data Try It Out Data Readers 1 Copy the project C:\BegVC #Databases\ Chapter06\Ex0601 - Executing Commands to a new project, C:\BegVC #Databases\ Chapter06\Ex0602 - Data Readers (Copy and rename the directory, open it in Visual C# Express, and rename the solution and project.) 2 Open app.config and change the path to the local database file to... that up to 50 percent of large-scale e-commerce web sites — and up to 75 percent of smaller sites — may be vulnerable to SQL injection attacks In the following Try It Out, you configure a connection and execute a command through it Try It Out Executing Commands 1 Open Visual C# Express and create a new Console application called Ex0601 - Executing Commands Save the project in the C:\BegVC #Databases\ Chapter06... name=”FolktaleDBConnectionString” connectionString=”Data Source=.\SQLEXPRESS; AttachDbFilename= C:\BegVC #Databases\ Chapter06\Ex0601 - Executing Commands\FolktaleDB.mdf; Integrated Security=True; 202 44063c06.qxd:WroxBeg 9/12/06 3 :52 PM Page 203 Accessing Databases Programmatically User Instance=True”/> 5 6 Add a project reference to System.Configuration by selecting Project ➪ Add Reference... all you need to access data By using command and data reader objects through configured connections, you can interact with data in databases in any way you want In fact, many developers look no further than this 212 44063c06.qxd:WroxBeg 9/12/06 3 :52 PM Page 213 Accessing Databases Programmatically However, there are additional classes in the NET Framework to make things easier for you Using commands... executes it, and displays the result Because the result is a single value, the SqlCommand.ExecuteScalar() method is used, and the result is cast to an int value 204 44063c06.qxd:WroxBeg 9/12/06 3 :52 PM Page 2 05 Accessing Databases Programmatically The database access code uses exception handling as discussed earlier in the chapter If something goes wrong, the exception message is simply output to the user,... Console.WriteLine(“Press ENTER to close.”); Console.ReadLine(); } 4 Execute the application and enter a table name — Character, for example Figure 6-4 shows the result 5 Close the application and Visual C# Express Figure 6-4: Table data output 211 44063c06.qxd:WroxBeg 9/12/06 3 :52 PM Page 212 Chapter 6 How It Works In this example, some modifications are made to the code from the previous example to use a data reader to... specified column must be obtained by the data reader before it can return a value, but that’s relatively minor, and it certainly makes your code look readable 208 44063c06.qxd:WroxBeg 9/12/06 3 :52 PM Page 209 Accessing Databases Programmatically When using the typed methods to obtain column values, you should be aware of what happens in the case of null values When dealing with value types, null values are... ConfigurationManager.ConnectionStrings[“MyConnectionString”].ConnectionString); try { conn.Open(); } catch (Exception ex) { // Handle exception } finally { conn.Close(); } 196 44063c06.qxd:WroxBeg 9/12/06 3 :52 PM Page 197 Accessing Databases Programmatically There is no need to test the SqlConnection.State property in the finally block because attempting to close a connection that is already closed does not generate . Views 1. Copy the C:BegVC #Databases Chapter 05 Ex 050 3 - Modifying List Data example directory from the earlier Try It Out to a new directory, C:BegVC #Databases Chapter 05 Ex 050 5 - Master-Detail View . 2 FormView g. DetailsForm 4. Copy the project C:BegVC #Databases Chapter 05 Ex 050 5 - Master-Detail View to a new project, C:BegVC #Databases Chapter 05 Q 050 4 - List Filtering. Modify this proj- ect by. should be 200 pixels. Figure 5- 25 shows the expected result. Figure 5- 25: Exercise 4 goal 192 Chapter 5 44063c 05. qxd:WroxBeg 9/12/06 10:36 PM Page 192 6 Accessing Databases Programmatically As