ASP.NET 4 Unleased - p 91 pps

10 171 0
ASP.NET 4 Unleased - p 91 pps

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

Thông tin tài liệu

ptg 874 CHAPTER 19 Building Data Access Components with ADO.NET </div> </form> </body> </html> Returning a Single Value If you need to return a single value from a database query, you can use the SqlCommand.ExecuteScalar() method. This method always returns the value of the first column from the first row of a resultset. Even when a query returns hundreds of columns and billions of rows, everything is ignored except for the value of the first column from the first row. For example, the page in Listing 19.17 contains a lookup form. If you enter the title of a movie, the movie’s total box office returns display in a Label control (see Figure 19.8). FIGURE 19.8 Retrieving a value with ExecuteScalar(). LISTING 19.17 ShowExecuteScalar.aspx <%@ Page Language=”C#” %> <%@ Import Namespace=”System.Data” %> <%@ Import Namespace=”System.Data.SqlClient” %> <%@ Import Namespace=”System.Web.Configuration” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” From the Library of Wow! eBook ptg 875 Connected Data Access 19 “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”> <script runat=”server”> protected void btnSearch_Click(object sender, EventArgs e) { string connectionString = WebConfigurationManager.ConnectionStrings[“Movies”].ConnectionString; SqlConnection con = new SqlConnection(connectionString); SqlCommand cmd = new SqlCommand(“SELECT BoxOfficeTotals FROM Movies WHERE Title=@Title”, con); cmd.Parameters.AddWithValue(“@Title”, txtTitle.Text); using (con) { con.Open(); Object result = cmd.ExecuteScalar(); if (result != null) lblResult.Text = String.Format(“{0:c}”, result); else lblResult.Text = “No match!”; } } </script> <html xmlns=”http://www.w3.org/1999/xhtml” > <head id=”Head1” runat=”server”> <title>Show Execute Scalar</title> </head> <body> <form id=”form1” runat=”server”> <div> <h1>Box Office Totals</h1> <asp:Label id=”lblTitle” Text=”Movie Title:” AssociatedControlID=”txtTitle” Runat=”server” /> <asp:TextBox id=”txtTitle” Runat=”server” /> <asp:Button id=”btnSearch” From the Library of Wow! eBook ptg 876 CHAPTER 19 Building Data Access Components with ADO.NET Text=”Search” OnClick=”btnSearch_Click” Runat=”server” /> <hr /> <asp:Label id=”lblResult” Runat=”server” /> </div> </form> </body> </html> The ExecuteScalar() method returns a value of type Object. This means that you must cast the value returned from ExecuteScalar() to a particular type before you do anything with the value. In Listing 19.17, after verifying that a value is returned, the value is cast to a decimal. You have a choice here. Rather than use the ExecuteScalar() method, you can use an output parameter. You can use either method to return a single value from a database. There is no real difference in performance between using the ExecuteScalar() method with a stored procedure or using an output parameter. The approach you take is largely a matter of preference. NOTE For performance comparisons between ExecuteScalar and output parameters, see Priya Dhawan’s article at the Microsoft MSDN website (msdn.Microsoft.com), “Performance Comparison: Data Access Techniques.” Returning a Resultset If you need to return multiple rows of data with a SqlCommand object, you can call the SqlCommand.ExecuteReader() method. This method returns a SqlDataReader that you can use to fetch each row of records from the database. For example, the data access component in Listing 19.18 contains a method named GetAll() that returns all the movies from the Movies database table. After the ExecuteReader() method is called, each row is retrieved from the SqlDataReader and dumped into a generic List collection. From the Library of Wow! eBook ptg 877 Connected Data Access 19 LISTING 19.18 App_Code\Movie6.cs using System; using System.Data; using System.Data.SqlClient; using System.Web.Configuration; using System.Collections.Generic; public class Movie6 { private static readonly string _connectionString; private string _title; private string _director; public string Title { get { return _title; } set { _title = value; } } public string Director { get { return _director; } set { _director = value; } } public List<Movie6> GetAll() { List<Movie6> results = new List<Movie6>(); SqlConnection con = new SqlConnection(_connectionString); SqlCommand cmd = new SqlCommand(“SELECT Title,Director FROM Movies”, con); using (con) { con.Open(); SqlDataReader reader = cmd.ExecuteReader(); while (reader.Read()) { Movie6 newMovie = new Movie6(); newMovie.Title = (string)reader[“Title”]; newMovie.Director = (string)reader[“Director”]; results.Add(newMovie); } } return results; } From the Library of Wow! eBook ptg 878 CHAPTER 19 Building Data Access Components with ADO.NET static Movie6() { _connectionString = WebConfigurationManager.ConnectionStrings[“Movies”].ConnectionString; } } The page in Listing 19.19 contains a GridView bound to an ObjectDataSource that repre- sents the component in Listing 19.18 (see Figure 19.9). FIGURE 19.9 Returning a resultset. LISTING 19.19 ShowMovie6.aspx <%@ Page Language=”C#” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”> <html xmlns=”http://www.w3.org/1999/xhtml” > <head id=”Head1” runat=”server”> <title>Show Movie6</title> </head> <body> <form id=”form1” runat=”server”> <div> From the Library of Wow! eBook ptg 879 Connected Data Access 19 <asp:GridView id=”grdMovies” DataSourceID=”srcMovies” Runat=”server” /> <asp:ObjectDataSource id=”srcMovies” TypeName=”Movie6” SelectMethod=”GetAll” Runat=”server” /> </div> </form> </body> </html> The component in Listing 19.18 copies all the records from the SqlDataReader to a collec- tion before returning the results of the query. If you want to skip the copying step, and not add the records to a collection, you can pass a CommandBehavior.CloseConnection parameter to the ExecuteReader() method. This parameter causes the database connection associated with the SqlDataReader to close automatically after all the records have been fetched from the SqlDataReader. The component in Listing 19.20 illustrates how you can use CommandBehavior.CloseConnection with the ExecuteReader() method. LISTING 19.20 App_Code\Movie7.cs using System; using System.Data; using System.Data.SqlClient; using System.Web.Configuration; using System.Collections.Generic; public class Movie7 { private static readonly string _connectionString; public SqlDataReader GetAll() { SqlConnection con = new SqlConnection(_connectionString); SqlCommand cmd = new SqlCommand(“SELECT Title,Director FROM Movies”, con); con.Open(); return cmd.ExecuteReader(CommandBehavior.CloseConnection); } From the Library of Wow! eBook ptg 880 CHAPTER 19 Building Data Access Components with ADO.NET static Movie7() { _connectionString = WebConfigurationManager.ConnectionStrings[“Movies”].ConnectionString; } } The page in Listing 19.21 displays the records returned from the component in Listing 19.20 in GridView. LISTING 19.21 ShowMovie7.aspx <%@ Page Language=”C#” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”> <html xmlns=”http://www.w3.org/1999/xhtml” > <head id=”Head1” runat=”server”> <title>Show Movie7</title> </head> <body> <form id=”form1” runat=”server”> <div> <asp:GridView id=”grdMovies” DataSourceID=”srcMovies” Runat=”server” /> <asp:ObjectDataSource id=”srcMovies” TypeName=”Movie7” SelectMethod=”GetAll” Runat=”server” /> </div> </form> </body> </html> The CommandBehavior.CloseConnection parameter enables you to return a SqlDataReader from a method. When all the records are read from the SqlDataReader, the CommandBehavior.CloseConnection parameter causes the SqlConnection object associated with the SqlDataReader to close automatically. From the Library of Wow! eBook ptg 881 Connected Data Access 19 The big disadvantage of using the CommandBehavior.CloseConnection parameter is that it prevents you from adding any exception handling code. You can’t use a Using statement or Try Catch statement with the SqlConnection created in the component in Listing 19.19. A Using statement or Try Catch statement would force the SqlConnection to close before the SqlDataReader is returned from the method. Using the DataReader Object The DataReader object represents the results of a database query. You get a DataReader by calling a Command object’s ExecuteReader() method. You can verify whether a DataReader represents any rows by checking the HasRows prop- erty or calling the Read() method. The Read() method returns true when the DataReader can advance to a new row. (Calling this method also advances you to the next row.) The DataReader represents a single row of data at a time. To get the next row of data, you need to call the Read() method. When you get to the last row, the Read() method returns False. There are multiple ways to refer to the columns returned by a DataReader. For example, imagine that you use a SqlDataReader named reader to represent the following query: SELECT Title, Director FROM Movies If you want to retrieve the value of the Title column for the current row represented by a DataReader, you can use any of the following methods: string title = (string)reader[“Title”]; string title = (string)reader[0]; string title = reader.GetString(0); SqlString title = reader.GetSqlString(0); The first method returns the Title column by name. The value of the Title column is returned as an Object. Therefore, you must cast the value to a string before you can assign the value to a string variable. The second method returns the Title column by position. It also returns the value of the Title column as an Object, so you must cast the value before using it. The third method returns the Title column by position. However, it retrieves the value as a String value. You don’t need to cast the value in this case. Finally, the last method returns the Title column by position; however, it returns the value as a SqlString rather than a normal String. A SqlString represents the value using the specialized data types defined in the System.Data.SqlTypes namespace. There are trade-offs between the different methods of returning a column value. Retrieving a column by its position rather than its name is faster. However, this technique also makes your code more brittle. If the order of your columns changes in your query, your code no longer works. From the Library of Wow! eBook ptg 882 CHAPTER 19 Building Data Access Components with ADO.NET Returning Multiple Resultsets A single database query can return multiple resultsets. For example, the following query returns the contents of both the MovieCategories and Movies tables as separate resultsets: SELECT * FROM MoviesCategories;SELECT * FROM Movies A semicolon is used to separate the two queries. Executing multiple queries in one shot can result in better performance. When you execute multiple queries with a single command, you don’t tie up multiple database connections. The component in Listing 19.22 illustrates how you can retrieve multiple resultsets with a single query when using a SqlDataReader. The GetMovieData() method returns two collec- tions: a collection representing MovieCategories and a collection representing Movies. LISTING 19.22 App_Code\DataLayer1.cs using System; using System.Data; using System.Data.SqlClient; using System.Web.Configuration; using System.Collections.Generic; public class DataLayer1 { private static readonly string _connectionString; public class MovieCategory { private int _id; private string _name; public int Id { get { return _id; } set { _id = value; } } public string Name { get { return _name; } set { _name = value; } } } public class Movie { From the Library of Wow! eBook ptg 883 Connected Data Access 19 private string _title; private int _categoryId; public string Title { get { return _title; } set { _title = value; } } public int CategoryId { get { return _categoryId; } set { _categoryId = value; } } } public static void GetMovieData( List<DataLayer1.MovieCategory> movieCategories, List<DataLayer1.Movie> movies) { string commandText = “SELECT Id,Name FROM MovieCategories;SELECT Title,CategoryId FROM Movies”; SqlConnection con = new SqlConnection(_connectionString); SqlCommand cmd = new SqlCommand(commandText, con); using (con) { // Execute command con.Open(); SqlDataReader reader = cmd.ExecuteReader(); // Create movie categories while (reader.Read()) { DataLayer1.MovieCategory newCategory = ➥ new DataLayer1.MovieCategory(); newCategory.Id = (int)reader[“Id”]; newCategory.Name = (string)reader[“Name”]; movieCategories.Add(newCategory); } // Move to next result set reader.NextResult(); // Create movies while (reader.Read()) From the Library of Wow! eBook . procedure or using an output parameter. The approach you take is largely a matter of preference. NOTE For performance comparisons between ExecuteScalar and output parameters, see Priya Dhawan’s article. that repre- sents the component in Listing 19.18 (see Figure 19.9). FIGURE 19.9 Returning a resultset. LISTING 19.19 ShowMovie6.aspx <%@ Page Language=”C#” %> <!DOCTYPE html PUBLIC -/ /W3C//DTD. page in Listing 19.21 displays the records returned from the component in Listing 19.20 in GridView. LISTING 19.21 ShowMovie7.aspx <%@ Page Language=”C#” %> <!DOCTYPE html PUBLIC -/ /W3C//DTD

Ngày đăng: 06/07/2014, 18:20

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

  • Đang cập nhật ...

Tài liệu liên quan