This method returns the result set in a DataReader object, which you can then use to read the rows returned by the database.. For example, the following code creates the required objects
Trang 1Executing SELECT Statements and TableDirect Commands
A TableDirect command is actually a SELECT statement that returns all the rows and columns for a specified table A Command object has three methods you can use to execute a SELECT statement or TableDirect command Table 8.4 shows these methods, which you'll learn how to use in the following sections
Table 8.4: METHODS THAT RETRIEVE INFORMATION FROM THE DATABASE
TYPE
DESCRIPTION
ExecuteReader() SqlDataReader Used to execute SQL SELECT statements,
TableDirect commands or stored procedure calls that return a result set Returns the result set in a DataReader object
ExecuteScalar() object Used to execute SQL SELECT statements that
return a single value (any other values are ignored) Returns the single value as an object ExecuteXmlReader() XmlReader Used to execute SQL SELECT statements that
return XML data Returns the result set in an XmlReader object Applies only to the SqlCommand class
Executing a SELECT Statement Using the ExecuteReader() Method
Let's take a look at an example that executes a SELECT statement using the
ExecuteReader() method This method returns the result set in a DataReader object, which you can then use to read the rows returned by the database For example, the following code creates the required objects and executes a SELECT statement that retrieves the top five rows from the Customers table:
SqlConnection mySqlConnection =
new SqlConnection(
"server=localhost;database=Northwind;uid=sa;pwd=sa"
);
SqlCommand mySqlCommand = mySqlConnection.CreateCommand();
mySqlCommand.CommandText =
"SELECT TOP 5 CustomerID, CompanyName, ContactName, Address " +
"FROM Customers " +
"ORDER BY CustomerID";
mySqlConnection.Open();
SqlDataReader mySqlDataReader = mySqlCommand.ExecuteReader();
Trang 2Tip You'll notice that I didn't call the Open() method of the SqlConnection object until just before calling the ExecuteReader() method of the SqlCommand object This is
intentional By opening the connection at the very last moment, you minimize time spent connected to the database and therefore conserve database resources
The result set returned by mySqlCommand is stored in mySqlDataReader You then read the rows from mySqlDataReader using the Read() method This method returns the Boolean true value when there is another row to read, otherwise it returns false You can read an individual column value in a row from mySqlDataReader by passing the name of the column in square brackets For example, to read the CustomerID column, you use mySqlDataReader["CustomerID"]
Note You can also specify the column you want to get by passing a numeric value in
brackets For example, my SqlDataReader[0] also returns the CustomerID column
value 0 corresponds to the first column in the table, which in this example is the
CustomerID column
You can use the Read() method in a while loop to read each row in turn, as shown in the following example:
while (mySqlDataReader.Read())
{
Console.WriteLine("mySqlDataReader[\" CustomerID\"] = " +
mySqlDataReader["CustomerID"]);
Console.WriteLine("mySqlDataReader[\" CompanyName\"] = " +
mySqlDataReader["CompanyName"]);
Console.WriteLine("mySqlDataReader[\" ContactName\"] = " +
mySqlDataReader["ContactName"]);
Console.WriteLine("mySqlDataReader[\" Address\"] = " +
mySqlDataReader["Address"]);
}
Listing 8.1 illustrates a complete program that uses the code examples shown in this section
Listing 8.1: EXECUTESELECT.CS
/*
ExecuteSelect.cs illustrates how to execute a SELECT
statement using a SqlCommand object
*/
using System;
Trang 3using System.Data;
using System.Data.SqlClient;
class ExecuteSelect
{
public static void Main()
{
// create a SqlConnection object to connect to the database
SqlConnection mySqlConnection =
new SqlConnection(
"server=localhost;database=Northwind;uid=sa;pwd=sa"
);
// create a SqlCommand object
SqlCommand mySqlCommand = mySqlConnection.CreateCommand();
// set the CommandText property of the SqlCommand object to
// the SELECT statement
mySqlCommand.CommandText =
"SELECT TOP 5 CustomerID, CompanyName, ContactName, Address " + "FROM Customers " +
"ORDER BY CustomerID";
// open the database connection using the
// Open() method of the SqlConnection object
mySqlConnection.Open();
// create a SqlDataReader object and call the ExecuteReader()
// method of the SqlCommand object to run the SQL SELECT statement SqlDataReader mySqlDataReader = mySqlCommand.ExecuteReader();
// read the rows from the SqlDataReader object using
// the Read() method
while (mySqlDataReader.Read())
{
Console.WriteLine("mySqlDataReader[\" CustomerID\"] = " +
mySqlDataReader["CustomerID"]);
Console.WriteLine("mySqlDataReader[\" CompanyName\"] = " +
mySqlDataReader["CompanyName"]);
Console.WriteLine("mySqlDataReader[\" ContactName\"] = " +
mySqlDataReader["ContactName"]);
Console.WriteLine("mySqlDataReader[\" Address\"] = " +
mySqlDataReader["Address"]);
Trang 4}
// close the SqlDataReader object using the Close() method
mySqlDataReader.Close();
// close the SqlConnection object using the Close() method
mySqlConnection.Close();
}
}
The output from this program is as follows:
mySqlDataReader["CustomerID"] = ALFKI
mySqlDataReader["CompanyName"] = Alfreds Futterkiste
mySqlDataReader["ContactName"] = Maria Anders
mySqlDataReader["Address"] = Obere Str 57
mySqlDataReader["CustomerID"] = ANATR
mySqlDataReader["CompanyName"] = Ana Trujillo3 Emparedados y helados
mySqlDataReader["ContactName"] = Ana Trujillo
mySqlDataReader["Address"] = Avda de la Constitución 2222
mySqlDataReader["CustomerID"] = ANTON
mySqlDataReader["CompanyName"] = Antonio Moreno Taquería
mySqlDataReader["ContactName"] = Antonio Moreno
mySqlDataReader["Address"] = Mataderos 2312
mySqlDataReader["CustomerID"] = AROUT
mySqlDataReader["CompanyName"] = Around the Horn
mySqlDataReader["ContactName"] = Thomas Hardy
mySqlDataReader["Address"] = 120 Hanover Sq
mySqlDataReader["CustomerID"] = BERGS
mySqlDataReader["CompanyName"] = Berglunds snabbköp
mySqlDataReader["ContactName"] = Christina Berglund
mySqlDataReader["Address"] = Berguvsvägen 8
Controlling the Command Behavior Using the ExecuteReader() Method
The ExecuteReader() method accepts an optional parameter that controls the command behavior The values for this parameter come from the System.Data.CommandBehavior enumeration, for which values are shown in Table 8.5
Table 8.5: CommandBehavior ENUMERATION VALUES
Trang 5Table 8.5: CommandBehavior ENUMERATION VALUES
CloseConnection Specifies that when the associated DataReader object is closed, the
Connection object is also closed
Default Indicates the Command object may return multiple result sets
KeyInfo Specifies the Command object returns information about the primary
key columns in the result set
SchemaOnly Indicates the Command object returns information only about the
columns
SequentialAccess Enables a DataReader object to read rows that have columns
containing large binary values SequentialAccess causes the DataReader to read the data as a stream You then use the GetBytes()
or GetChars() methods of the DataReader to read the stream Note: you'll learn the details of DataReader objects in the next chapter
SingleResult Specifies the Command object returns a single result set
SingleRow Indicates the Command object returns a single row
You'll see how to use the SingleRow and SchemaOnly command behaviors next
Using the SingleRow Command Behavior
You use the SingleRow command behavior to indicate that your Command object returns
a single row For example, let's say you have a Command object named mySqlCommand with the CommandText property set as follows:
mySqlCommand.CommandText =
"SELECT ProductID, ProductName, QuantityPerUnit, UnitPrice " +
"FROM Products";
Next, the following example passes the CommandBehavior.SingleRow value to the ExecuteReader() method, indicating that the Command object retrieves only the first row:
SqlDataReader mySqlDataReader =
mySqlCommand.ExecuteReader(CommandBehavior.SingleRow);
Even though the earlier SELECT statement indicates that all the rows are to be retrieved
from the Products table, the mySqlDataReader object will be able to read only the first row
Listing 8.2 illustrates the effect of using CommandBehavior.SingleRow
Trang 6Listing 8.2: SINGLEROWCOMMANDBEHAVIOR.CS
/*
SingleRowCommandBehavior.cs illustrates how to control
the command behavior to return a single row
*/
using System;
using System.Data;
using System.Data.SqlClient;
class SingleRowCommandBehavior
{
public static void Main()
{
SqlConnection mySqlConnection =
new SqlConnection(
"server=localhost;database=Northwind;uid=sa;pwd=sa"
);
SqlCommand mySqlCommand = mySqlConnection.CreateCommand(); mySqlCommand.CommandText =
"SELECT ProductID, ProductName, QuantityPerUnit, UnitPrice " + "FROM Products";
mySqlConnection.Open();
// pass the CommandBehavior.SingleRow value to the
// ExecuteReader() method, indicating that the Command object
// only returns a single row
SqlDataReader mySqlDataReader =
mySqlCommand.ExecuteReader(CommandBehavior.SingleRow);
while (mySqlDataReader.Read())
{
Console.WriteLine("mySqlDataReader[\" ProductID\"] = " +
mySqlDataReader["ProductID"]);
Console.WriteLine("mySqlDataReader[\" ProductName\"] = " + mySqlDataReader["ProductName"]);
Console.WriteLine("mySqlDataReader[\" QuantityPerUnit\"] = " + mySqlDataReader["QuantityPerUnit"]);
Console.WriteLine("mySqlDataReader[\" UnitPrice\"] = " +
mySqlDataReader["UnitPrice"]);
}
Trang 7mySqlDataReader.Close();
mySqlConnection.Close();
}
}
The output from this program is as follows:
mySqlDataReader["ProductID"] = 1
mySqlDataReader["ProductName"] = Chai
mySqlDataReader["QuantityPerUnit"] = 10 boxes x 20 bags
mySqlDataReader["UnitPrice"] = 18
Using the SchemaOnly Command Behavior
You use the SchemaOnly command behavior to indicate that your Command object returns information only about the columns retrieved by a SELECT statement, or all the columns when you use a TableDirect command
For example, let's say you have a Command object named mySqlCommand with the CommandText property set as follows:
mySqlCommand.CommandText =
"SELECT ProductID, ProductName, UnitPrice " +
"FROM Products " +
"WHERE ProductID = 1";
Next, the following example passes the CommandBehavior.SchemaOnly value to the ExecuteReader() method, indicating that the Command object returns information about the schema:
SqlDataReader productsSqlDataReader =
mySqlCommand.ExecuteReader(CommandBehavior.SchemaOnly);
In this example, since the ProductID, ProductName, and UnitPrice columns of the Products table were used in the earlier SELECT statement, information about those columns is retrieved instead of the column values
You get the information about the columns using the GetSchemaTable() method of your SqlData-Reader object The GetSchemaTable() method returns a DataTable object with columns that contain the details of the retrieved database columns:
DataTable myDataTable = productsSqlDataReader.GetSchemaTable();
Trang 8To display the values in the DataTable object, you can use the following loop that
displays the DataTable column names and the contents of each DataTable column:
foreach (DataRow myDataRow in myDataTable.Rows)
{
foreach (DataColumn myDataColumn in myDataTable.Columns)
{
Console.WriteLine(myDataColumn + "= " +
myDataRow[myDataColumn]);
if (myDataColumn.ToString() == "ProviderType")
{
Console.WriteLine(myDataColumn + "= " +
((System.Data.SqlDbType) myDataRow[myDataColumn]));
}
}
}
Notice that this code features two foreach loops The outer loop iterates over the
DataRow objects in myDataTable, and the inner loop iterates over the DataColumn
objects in the current DataRow Don't worry too much about the details of accessing a DataTable just yet: you'll learn the details in Chapter 10, "Using DataSet Objects to Store Data."
The if statement in the inner foreach loop requires a little explanation What I'm doing is examining the myDataColumn to see if it contains the ProviderType ProviderType contains a number value that indicates the SQL Server type of the database column I cast this number to System.Data.SqlDbType, which is an enumeration that defines the SQL Server column types, as you'll see later in the "Supplying Parameters to Commands" section Table 8.9 in that section shows the SqlDbType enumeration values By casting the ProviderType number to SqlDbType, you can see the actual name of the SQL Server column type
The first iteration of the outer loop displays all the DataColumn object values for the first DataRow object This cause the following output to be produced and shows the schema details for the ProductID column; notice the ProviderType number and name that indicate ProductID is a SQL Server int:
ColumnName = ProductID
ColumnOrdinal = 0
ColumnSize = 4
NumericPrecision = 0
NumericScale = 0
IsUnique =
Trang 9IsKey =
BaseCatalogName =
BaseColumnName = ProductID
BaseSchemaName =
BaseTableName =
DataType = System.Int32
AllowDBNull = False
ProviderType = 8
ProviderType = Int
IsAliased =
IsExpression =
IsIdentity = True
IsAutoIncrement = True
IsRowVersion =
IsHidden =
IsLong = False
IsReadOnly = True
The meanings of these results are shown in Table 8.6
Table 8.6: SCHEMA COLUMN VALUES
ColumnName Name of the column
ColumnOrdinal Ordinal of the column
ColumnSize Maximum length (in characters) of a column value For fixed-length
SQL Server types such as int, the ColumnSize is the length of that type
NumericPrecision Total number of digits used to represent a floating-point type An
example of a floating-point type is the SQL Server float type The total number of digits includes the digits to the left and right of the decimal point
NumericScale Total number of digits to the right of the decimal point in a
floating-point type
IsUnique Boolean true/false value that indicates whether two rows can have the
same value in the current column
IsKey Boolean true/false value that indicates whether the column is part of
the primary key
BaseCatalogName Name of the catalog in the database that contains the column
BaseCatalogName defaults to null
BaseColumnName Name of the column in the database This will differ from the
Trang 10Table 8.6: SCHEMA COLUMN VALUES
ColumnName if you use an alias for the column BaseColumnName defaults to null
BaseSchemaName Name of the schema in the database that contains the column
BaseSchemaName defaults to null
BaseTableName Name of the table or view in the database that contains the column
BaseTableName defaults to null
DataType .NET type used to represent the column You'll learn about the NET
types in the next chapter
AllowDBNull Boolean true/false value that indicates whether the column can accept
a database null value
ProviderType Indicates the column's database type
IsAliased Boolean true/false value that indicates whether the column is an alias IsExpression Boolean true/false value that indicates whether the column is an
expression
IsIdentity Boolean true/false value that indicates whether the column is an
identity
IsAutoIncrement Boolean true/false value that indicates whether the column is
automatically assigned a value for a new row and that value is automatically incremented
IsRowVersion Boolean true/false value that indicates whether the column contains a
persistent row identifier that cannot be written to
IsHidden Boolean true/false value that indicates whether the column is hidden IsLong Boolean true/false value that indicates whether the column contains a
binary long object (BLOB) A BLOB contains a long string of binary data
IsReadOnly Boolean true/false value that indicates whether the column can be
modified
Listing 8.3 illustrates the effect of using CommandBehavior.SchemaOnly and displays the schema details for the ProductID, ProductName, and UnitPrice columns