When you execute the SqlCommand, the following command is sent to Microsoft SQL Server: exec sp_executesql N’INSERT Titles Title VALUES @Title’, ➥N’@Title nvarchar17’, @Title = N’ASP.NET
Trang 1The first statement creates a SqlCommand object that represents a SQL INSERT command
The command includes a parameter named @Title
The second statement adds a SqlParameter to the SqlCommand object’s Parameters
collec-tion The AddWithValue() method enables you to add a parameter with a certain name
and value In this case, the method supplies the value for the @Title parameter
When you execute the SqlCommand, the following command is sent to Microsoft
SQL Server:
exec sp_executesql N’INSERT Titles (Title) VALUES (@Title)’,
➥N’@Title nvarchar(17)’, @Title = N’ASP.NET 4.0 Unleashed’
The SqlCommand object calls the sp_executesql stored procedure when it executes a
command In this case, it passes the type, size, and value of the @Title parameter to the
sp_executesql stored procedure
When you use AddWithValue(), the SqlCommand object infers the type and size of the
para-meter for you The method assumes that string values are SQL NVarChar values, integer
values are SQL Int values, decimal values are SQL decimal values, and so on
As an alternative to using the AddWithValue() method, you can create a SqlParameter
explicitly and add the SqlParameter to a SqlCommand object’s Parameters collection The
advantage of creating a parameter explicitly is that you can specify parameter properties
explicitly, such as its name, type, size, precision, scale, and direction
For example, the following code creates a parameter named @Title with a particular data
type, size, and value:
SqlCommand cmd = new SqlCommand(“INSERT Titles (Title) VALUES (@Title)”, con);
SqlParameter paramTitle = new SqlParameter();
paramTitle.ParameterName = “@Title”;
paramTitle.SqlDbType = SqlDbType.NVarChar;
paramTitle.Size = 50;
paramTitle.Value = “ASP.NET 4.0 Unleashed”;
cmd.Parameters.Add(paramTitle);
If this seems like a lot of code to do something simple, you can use one of the overloads
of the Add() method to create a new SqlParameter like this:
SqlCommand cmd = new SqlCommand(“INSERT Test (Title) VALUES (@Title)”, con);
cmd.Parameters.Add(“@Title”, SqlDbType.NVarChar,50).Value = “ASP.NET 4.0
➥Unleashed”;
In general, in this book and in the code that I write, I use the AddWithValue() method to
create parameters I like the AddWithValue() method because it involves the least typing
Trang 2Executing a Command That Represents a Stored Procedure
You can use a SqlCommand object to represent a Microsoft SQL Server stored procedure For
example, you can use the following two statements to create a SqlCommand object that
represents a stored procedure named GetTitles:
SqlCommand cmd = new SqlCommand(“GetTitles”, con);
cmd.CommandType = CommandType.StoredProcedure;
When you execute this SqlCommand, the GetTitles stored procedure is executed When
you create SqlParameters for a SqlCommand that represents a stored procedure, the
SqlParameters represent stored procedure parameters The modified Movie component in
Listing 19.9 uses stored procedures to retrieve and update movie records
LISTING 19.9 App_Code\Movie4.cs
using System;
using System.Data;
using System.Data.SqlClient;
using System.Web.Configuration;
using System.Collections.Generic;
public class Movie4
{
private static readonly string _connectionString;
private int _id;
private string _title;
private string _director;
public int Id
{
get { return _id; }
set { _id = value; }
}
public string Title
{
get { return _title; }
set { _title = value; }
}
public string Director
{
get { return _director; }
set { _director = value; }
}
Trang 3public void Update(int id, string title, string director)
{
SqlConnection con = new SqlConnection(_connectionString);
SqlCommand cmd = new SqlCommand(“MovieUpdate”, con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue(“@Id”, id);
cmd.Parameters.AddWithValue(“@Title”, title);
cmd.Parameters.AddWithValue(“@Director”, director);
using (con)
{
con.Open();
cmd.ExecuteNonQuery();
}
}
public List<Movie4> GetAll()
{
List<Movie4> results = new List<Movie4>();
SqlConnection con = new SqlConnection(_connectionString);
SqlCommand cmd = new SqlCommand(“MovieSelect”, con);
cmd.CommandType = CommandType.StoredProcedure;
using (con)
{
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
Movie4 newMovie = new Movie4();
newMovie.Id = (int)reader[“Id”];
newMovie.Title = (string)reader[“Title”];
newMovie.Director = (string)reader[“Director”];
results.Add(newMovie);
}
}
return results;
}
static Movie4()
{
_connectionString =
WebConfigurationManager.ConnectionStrings[“Movies”].ConnectionString;
}
}
The component in Listing 19.9 uses the MovieSelect and MovieUpdate stored procedures
contained in Listing 19.10
Trang 4LISTING 19.10 MovieStoredProcedures.sql
CREATE PROCEDURE dbo.MovieSelect
AS
SELECT Id, Title, Director FROM Movies
CREATE PROCEDURE dbo.MovieUpdate
(
@Id int,
@Title NVarchar(100),
@Director NVarchar(100)
)
AS
UPDATE Movies SET
Title = @Title,
Director = @Director
WHERE Id = @Id
The ASP.NET page in Listing 19.11 contains a GridView that is bound to the modified
Movie component This GridView enables you to display and update movie records
LISTING 19.11 ShowMovie4.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 Movie4</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<asp:GridView
id=”grdMovies”
DataSourceID=”srcMovies”
DataKeyNames=”Id”
AutoGenerateEditButton=”true”
Runat=”server” />
<asp:ObjectDataSource
id=”srcMovies”
TypeName=”Movie4”
SelectMethod=”GetAll”
Trang 5UpdateMethod=”Update”
Runat=”server” />
</div>
</form>
</body>
</html>
You can use a SqlParameter to represent not only stored procedure input parameters, but
also to represent stored procedure return values and output parameters If you need to
return an integer value from a stored procedure, you can create a SqlParameter that
repre-sents a return value For example, the stored procedure in Listing 19.12 returns the
number of rows in the Movies database table
LISTING 19.12 GetMovieCount.sql
CREATE PROCEDURE dbo.GetMovieCount
AS
RETURN (SELECT COUNT(*) FROM Movies)
The page in Listing 19.13 displays the return value from the GetMovieCount stored
proce-dure with a Label control (see Figure 19.6)
FIGURE 19.6 Displaying a stored procedure return value
Trang 6LISTING 19.13 ShowMovieCount.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”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<script runat=”server”>
void Page_Load()
{
lblMovieCount.Text = GetMovieCount().ToString();
}
private int GetMovieCount()
{
int result = 0;
string connectionString =
WebConfigurationManager.ConnectionStrings[“Movies”].ConnectionString;
SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand(“GetMovieCount”, con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(“@ReturnVal”, SqlDbType.Int).Direction =
➥ParameterDirection.ReturnValue;
using (con)
{
con.Open();
cmd.ExecuteNonQuery();
result = (int)cmd.Parameters[“@ReturnVal”].Value;
}
return result;
}
</script>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head id=”Head1” runat=”server”>
<title>Show Movie Count</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
There are
<asp:Label
id=”lblMovieCount”
Runat=”server” />
Trang 7movies in the database
</div>
</form>
</body>
</html>
In Listing 19.13, a SqlParameter is created that has the name ReturnVal The name of the
SqlParameter is not important However, the SqlParameter.Direction property is set to
the value ReturnValue After the SqlCommand is executed, the return value can be retrieved
by reading the value of this parameter
A stored procedure has only one return value, and it must be an integer value If you need
to return more than one value, or values of a different data type than an integer, you need
to use stored procedure output parameters
For example, the stored procedure in Listing 19.14 returns movie titles and box office
totals The stored procedure includes an output parameter named @SumBoxOfficeTotals
This output parameter represents a sum of all box office totals
LISTING 19.14 GetBoxOfficeTotals.sql
CREATE PROCEDURE dbo.GetBoxOfficeTotals
(
@SumBoxOfficeTotals Money OUTPUT
)
AS
Assign Sum Box Office Totals
SELECT @SumBoxOfficeTotals = SUM(BoxOfficeTotals) FROM Movies
Return all rows
SELECT Title, BoxOfficeTotals FROM Movies
The data access component in Listing 19.15 contains a method named GetBoxOffice()
that calls the GetBoxOfficeTotals stored procedure The method adds an output
parame-ter to the SqlCommand object
LISTING 19.15 App_Code\Movie5.cs
using System;
using System.Data;
using System.Data.SqlClient;
using System.Web.Configuration;
using System.Collections.Generic;
public class Movie5
Trang 8{
private static readonly string _connectionString;
private string _title;
private decimal _boxOfficeTotals;
public string Title
{
get { return _title; }
set { _title = value; }
}
public decimal BoxOfficeTotals
{
get { return _boxOfficeTotals; }
set { _boxOfficeTotals = value; }
}
public List<Movie5> GetBoxOffice(out decimal SumBoxOfficeTotals)
{
List<Movie5> results = new List<Movie5>();
SqlConnection con = new SqlConnection(_connectionString);
SqlCommand cmd = new SqlCommand(“GetBoxOfficeTotals”, con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(“@SumBoxOfficeTotals”, SqlDbType.Money).Direction =
ParameterDirection.Output;
using (con)
{
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
Movie5 newMovie = new Movie5();
newMovie.Title = (string)reader[“Title”];
newMovie.BoxOfficeTotals = (decimal)reader[“BoxOfficeTotals”];
results.Add(newMovie);
}
reader.Close();
SumBoxOfficeTotals =
➥(decimal)cmd.Parameters[“@SumBoxOfficeTotals”].Value;
}
return results;
}
Trang 9static Movie5()
{
_connectionString =
WebConfigurationManager.ConnectionStrings[“Movies”].ConnectionString;
}
}
In Listing 19.15, the SqlDataReader is explicitly closed before the output parameter is
read If you do not close the SqlDataReader first, attempting to read the value of the
output parameter raises an exception
Finally, the page in Listing 19.16 displays the movie box office totals in a GridView In
addition, it displays the value of the output parameter in a Label control (see Figure 19.7)
FIGURE 19.7 Displaying an output parameter
LISTING 19.16 ShowMovie5.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”>
protected void srcMovies_Selected(object sender,
➥ObjectDataSourceStatusEventArgs e)
Trang 10{
decimal sum = (decimal)e.OutputParameters[“SumBoxOfficeTotals”];
lblSum.Text = sum.ToString(“c”);
}
</script>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head id=”Head1” runat=”server”>
<title>Show Movie5</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<asp:GridView
id=”grdMovies”
DataSourceID=”srcMovies”
AutoGenerateColumns=”false”
Runat=”server”>
<Columns>
<asp:BoundField DataField=”Title” HeaderText=”Title” />
<asp:BoundField
DataField=”BoxOfficeTotals”
HeaderText=”Box Office”
HtmlEncode=”false”
DataFormatString=”{0:c}” />
</Columns>
</asp:GridView>
<br />
Sum of Box Office Totals:
<asp:Label
id=”lblSum”
Runat=”server” />
<asp:ObjectDataSource
id=”srcMovies”
TypeName=”Movie5”
SelectMethod=”GetBoxOffice”
Runat=”server” OnSelected=”srcMovies_Selected”>
<SelectParameters>
<asp:Parameter
Name=”SumBoxOfficeTotals”
Type=”Decimal”
Direction=”Output” />
</SelectParameters>
</asp:ObjectDataSource>