ASP.NET 4 Unleased - p 96 pot

10 108 0
ASP.NET 4 Unleased - p 96 pot

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

Thông tin tài liệu

ptg 924 CHAPTER 19 Building Data Access Components with ADO.NET Creating the User-Defined Type After you have loaded the DBMovie assembly, you can create a new user-defined type from the assembly. Execute the following command: CREATE TYPE dbo.DBMovie EXTERNAL NAME DBMovie.DBMovie If you need to delete the type, you can execute the following command: DROP TYPE DBMovie After you have added the type, you can use it just like any other SQL Server native type. For example, you can create a new database table with the following command: CREATE TABLE DBMovies(Id INT IDENTITY, Movie DBMovie) You can insert a new record into this table with the following command: INSERT DBMovies (Movie) VALUES (‘Star Wars,George Lucas,12.34’) Finally, you can perform queries against the table with queries like the following: SELECT Id, Movie FROM DBMovies WHERE Movie.BoxOfficeTotals > 13.23 SELECT MAX(Movie.BoxOfficeTotals) FROM DBMovies SELECT Movie FROM DBMovies WHERE Movie.Director LIKE ‘g%’ I find the fact that you can execute queries like this truly amazing. Building a Data Access Layer with a User-Defined Type In this final section, let’s actually do something with our new user-defined type. We create a new data access component that uses the DBMovie class and an ASP.NET page that inter- faces with the component. Before we can do anything with the DBMovie type, we need to add a reference to the DBMovie.dll assembly to our application. In Visual Web Developer, select Website, Add Reference, and browse to the DBMovie.dll. Alternatively, you can create an application root Bin folder and copy the DBMovie.dll into the Bin folder. Our new data access component is contained in Listing 19.37. LISTING 19.37 App_Code\DBDataLayer.cs using System; using System.Data; using System.Data.SqlClient; using System.Web.Configuration; using System.Collections.Generic; From the Library of Wow! eBook ptg 925 Building Database Objects with the .NET Framework 19 public class DBDataLayer { private static readonly string _connectionString; public List<DBMovie> GetAll() { List<DBMovie> results = new List<DBMovie>(); SqlConnection con = new SqlConnection(_connectionString); SqlCommand cmd = new SqlCommand(“SELECT Movie FROM DBMovies”, con); using (con) { con.Open(); SqlDataReader reader = cmd.ExecuteReader(); while (reader.Read()) { DBMovie newMovie = (DBMovie)reader[“Movie”]; results.Add(newMovie); } } return results; } public void Insert(DBMovie movieToAdd) { SqlConnection con = new SqlConnection(_connectionString); SqlCommand cmd = new SqlCommand(“INSERT DBMovies (Movie) VALUES (@Movie)”, ➥ con); cmd.Parameters.Add(“@Movie”, SqlDbType.Udt); cmd.Parameters[“@Movie”].UdtTypeName = “DBMovie”; cmd.Parameters[“@Movie”].Value = movieToAdd; using (con) { con.Open(); cmd.ExecuteNonQuery(); } } static DBDataLayer() { _connectionString = WebConfigurationManager.ConnectionStrings[“Movies”].ConnectionString; } } From the Library of Wow! eBook ptg 926 CHAPTER 19 Building Data Access Components with ADO.NET The component in Listing 19.37 contains two methods: GetAll() and Insert(). The GetAll() method retrieves all the Movie objects from the DBMovies database table. You can cast the object represented by the DataReader directly to a DBMovie. The Insert() method adds a new DBMovie to the DBMovies database table. The method creates a normal ADO.NET Command object. However, a special parameter is added to the command that represents the DBMovie object. When you create a parameter that represents a user-defined type, you must specify a UdtTypeName property that represents the name of the user-defined type. In Listing 19.37, the value DBMovie is assigned to the UdtTypeName property. When the command executes, a new DBMovie object is added to the DBMovies database table. The page in Listing 19.38 contains a GridView, DetailsView, and ObjectDataSource control. The GridView displays all the movies from the DBMovies database table. The DetailsView control enables you to insert a new DBMovie into the database (see Figure 19.21). FIGURE 19.21 Displaying and inserting DBMovie objects. LISTING 19.38 ShowDBDataLayer.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”> From the Library of Wow! eBook ptg 927 Building Database Objects with the .NET Framework 19 <title>Show DBDataLayer</title> </head> <body> <form id=”form1” runat=”server”> <div> <asp:GridView id=”grdMovies” DataSourceID=”srcMovies” Runat=”server” /> <br /> <fieldset> <legend>Add Movie</legend> <asp:DetailsView id=”dtlMovie” DataSourceID=”srcMovies” DefaultMode=”Insert” AutoGenerateInsertButton=”true” AutoGenerateRows=”false” Runat=”server”> <Fields> <asp:BoundField DataField=”Title” HeaderText=”Title” /> <asp:BoundField DataField=”Director” HeaderText=”Director” /> <asp:BoundField DataField=”BoxOfficeTotals” HeaderText=”Box Office Totals” /> </Fields> </asp:DetailsView> </fieldset> <asp:ObjectDataSource id=”srcMovies” TypeName=”DBDataLayer” DataObjectTypeName=”DBMovie” SelectMethod=”GetAll” InsertMethod=”Insert” Runat=”server” /> </div> </form> </body> </html> From the Library of Wow! eBook ptg 928 CHAPTER 19 Building Data Access Components with ADO.NET Creating Stored Procedures with .NET Framework You can use .NET Framework to build a SQL stored procedure by mapping a stored proce- dure to a method defined in a class. You must complete the following steps: . Create an assembly that contains the stored procedure method. . Register the assembly with SQL Server. . Create a stored procedure based on the assembly. In this section, we create two stored procedures with .NET Framework. The first stored procedure, named GetRandomRow(), randomly returns a single row from a database table. The second stored procedure, GetRandomRows(), randomly returns a set of rows from a database table. Creating the Stored Procedure Assembly Creating a stored procedure with .NET Framework is easy. All you need to do is decorate a method with the SqlProcedure attribute. The method used for the stored procedure must satisfy two requirements. The method must be a shared (static) method. Furthermore, the method must be implemented either as a subroutine or as a function that returns an integer value. Within your method, you can take advantage of the SqlPipe class to send results back to your application. The SqlPipe class supports the following methods: . Send()—Enables you to send a DataReader, single-row resultset, or string. . ExecuteAndSend()—Enables you to execute a SqlCommand and send the results. . SendResultsStart()—Enables you to initiate the sending of a resultset. . SendResultsRow()—Enables you to send a single row of a resultset. . SendResultsEnd()—Enables you to end the sending of a resultset. Within the method used for creating the stored procedure, you can use ADO.NET objects such as the SqlCommand, SqlDataReader, and SqlDataAdapter objects in the normal way. However, rather than connect to the database by using a normal connection string, you can create something called a context connection. A context connection enables you to connect to the same database server as the stored procedure without authenticating. Here’s how you can initialize a SqlConnection to use a context connection: SqlConnection con = new SqlConnection(“context connection=true”); You don’t specify credentials or the location of the database in the connection string. Remember that the method actually executes within SQL Server. Therefore, you don’t need to connect to SQL Server in the normal way. The class in Listing 19.39 contains two methods named GetRandomRow() and GetRandomRows(). Both methods use a SqlDataAdapter to fill a DataTable with the From the Library of Wow! eBook ptg 929 Building Database Objects with the .NET Framework 19 contents of the Movies database table. The GetRandomRow() method grabs a single row from the DataTable and sends it back to the client. The GetRandomRows() method sends multiple rows back to the client. LISTING 19.39 RandomRows.cs using System; using System.Data; using System.Data.SqlClient; using Microsoft.SqlServer.Server; public class RandomRows { [SqlProcedure] public static void GetRandomRow() { // Dump all records from Movies into a DataTable SqlDataAdapter dad = new SqlDataAdapter( “SELECT Id,Title FROM Movies”, “context connection=true”); DataTable dtblMovies = new DataTable(); dad.Fill(dtblMovies); // Grab a random row Random rnd = new Random(); DataRow ranRow = dtblMovies.Rows[rnd.Next(dtblMovies.Rows.Count)]; // Build a SqlDataRecord that represents the row SqlDataRecord result = new SqlDataRecord( new SqlMetaData(“Id”, SqlDbType.Int), new SqlMetaData(“Title”, SqlDbType.NVarChar, ➥ 100)); result.SetSqlInt32(0, (int)ranRow[“Id”]); result.SetSqlString(1, (string)ranRow[“Title”]); // Send result SqlContext.Pipe.Send(result); } [SqlProcedure] public static void GetRandomRows(int rowsToReturn) { // Dump all records from Movies into a DataTable SqlDataAdapter dad = new SqlDataAdapter( “SELECT Id,Title FROM Movies”, “context connection=true”); DataTable dtblMovies = new DataTable(); dad.Fill(dtblMovies); From the Library of Wow! eBook ptg 930 CHAPTER 19 Building Data Access Components with ADO.NET // Send start record SqlDataRecord result = new SqlDataRecord(new SqlMetaData(“Id”, SqlDbType.Int),new SqlMetaData(“Title”, SqlDbType.NVarChar, 100)); SqlContext.Pipe.SendResultsStart(result); Random rnd = new Random(); for (int i = 0; i < rowsToReturn; i++) { // Grab a random row DataRow ranRow = dtblMovies.Rows[rnd.Next(dtblMovies.Rows.Count)]; // Set the record result.SetSqlInt32(0, (int)ranRow[“Id”]); result.SetSqlString(1, (string)ranRow[“Title”]); // Send record SqlContext.Pipe.SendResultsRow(result); } // Send end record SqlContext.Pipe.SendResultsEnd(); } } You need to compile the RandomRows class into a separate assembly (.dll file). After you create (and debug) the class, move the class from your App_Code folder to another folder in your application, such as the root folder. Next, open the SDK Command prompt and execute the following command: csc /t:library RandomRows.cs This command uses the C# command-line compiler to compile the RandomRows class into an assembly. Registering the Stored Procedure Assembly with SQL Server After you compile the RandomRows assembly, you are ready to deploy the assembly to SQL Server. You can load the assembly into SQL Server by executing the following command: CREATE ASSEMBLY RandomRows FROM ‘C:\RandomRows.dll’ You need to supply the proper path to the RandomRows.dll assembly on your hard drive. If you need to remove the assembly, you can execute the following command: DROP Assembly RandomRows From the Library of Wow! eBook ptg 931 Building Database Objects with the .NET Framework 19 Creating the Stored Procedures Now that the assembly is loaded, you can create two stored procedures that correspond to the two methods defined in the assembly. Execute the following two SQL commands: CREATE PROCEDURE GetRandomRow AS EXTERNAL NAME RandomRows.RandomRows.GetRandomRow CREATE PROCEDURE GetRandomRows(@rowsToReturn Int) AS EXTERNAL NAME RandomRows.RandomRows.GetRandomRows After you execute these two commands, you have two new stored procedures named GetRandomRow and GetRandomRows. You can treat these stored procedures just like normal stored procedures. For example, executing the following command displays three random movies from the Movies database: GetRandomRows 3 If you need to delete these stored procedures, you can execute the following two commands: DROP PROCEDURE GetRandomRow DROP PROCEDURE GetRandomRows Executing a .NET Stored Procedure from an ASP.NET Page After the two stored procedures have been created, you can use the stored procedures with an ASP.NET page. For example, the component in Listing 19.40 contains two methods that call the two stored procedures. LISTING 19.40 App_Code\RandomDataLayer.cs using System; using System.Data; using System.Data.SqlClient; using System.Web.Configuration; using System.Collections.Generic; public class RandomDataLayer { private static readonly string _connectionString; public List<String> GetRandomMovies() { List<String> results = new List<String>(); SqlConnection con = new SqlConnection(_connectionString); SqlCommand cmd = new SqlCommand(“GetRandomRows”, con); cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue(“@rowsToReturn”, 5); From the Library of Wow! eBook ptg 932 CHAPTER 19 Building Data Access Components with ADO.NET using (con) { con.Open(); SqlDataReader reader = cmd.ExecuteReader(); while (reader.Read()) results.Add((string)reader[“Title”]); } return results; } public static string GetRandomMovie() { string result = String.Empty; SqlConnection con = new SqlConnection(_connectionString); SqlCommand cmd = new SqlCommand(“GetRandomRow”, con); cmd.CommandType = CommandType.StoredProcedure; using (con) { con.Open(); SqlDataReader reader = cmd.ExecuteReader(); if (reader.Read()) result = (string)reader[“Title”]; } return result; } static RandomDataLayer() { _connectionString = WebConfigurationManager.ConnectionStrings[“Movies”].ConnectionString; } } In Listing 19.40, the GetRandomRow and GetRandomRows stored procedures are executed with the help of SqlCommand objects. The page in Listing 19.41 contains a GridView and ObjectDataSource control. The ObjectDataSource control represents the RandomDataLayer component. When you request the page, a single random movie title displays in a Label control. Furthermore, a list of five random movie titles displays in the GridView control (see Figure 19.22). From the Library of Wow! eBook ptg 933 Building Database Objects with the .NET Framework 19 LISTING 19.41 ShowRandomDataLayer.aspx <%@ Page Language=”C#” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”> <script runat=”server”> void Page_Load() { lblRandomMovie.Text = RandomDataLayer.GetRandomMovie(); } </script> <html xmlns=”http://www.w3.org/1999/xhtml” > <head id=”Head1” runat=”server”> <title>Show RandomDataLayer</title> </head> <body> <form id=”form1” runat=”server”> <div> Random Movie: <asp:Label id=”lblRandomMovie” FIGURE 19.22 Calling a .NET stored procedure from an ASP.NET page. From the Library of Wow! eBook . stored procedures, you can execute the following two commands: DROP PROCEDURE GetRandomRow DROP PROCEDURE GetRandomRows Executing a .NET Stored Procedure from an ASP. NET Page After the two stored procedures. can use the stored procedures with an ASP. NET page. For example, the component in Listing 19 .40 contains two methods that call the two stored procedures. LISTING 19 .40 App_CodeRandomDataLayer.cs using. special parameter is added to the command that represents the DBMovie object. When you create a parameter that represents a user-defined type, you must specify a UdtTypeName property that represents

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

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

Tài liệu liên quan