Sams Teach Yourself Visual Studio .NET 2003 in 21 Days

Sams Teach Yourself .Net in 21 Days

By Jason Beres

Using the Command Object and DataReaders

The Command object is used to execute SQL statements against a database. The SQL statements can be ad hoc text or the name of a stored procedure in SQL Server. The SqlCommand class is responsible for SQL Server access, and the OleDbCommand class is responsible for OLE DB data sources.

You create a Command object in one of two ways:

After you create a Command object, you set properties that indicate what the SQL statement is, the timeout, the connection information, and parameters if there are any in your SQL statement. Table 10.2 lists the common properties of the SqlCommand class and the OleDbCommand class.

Table 10.2. Common SqlCommand and OleDbCommand Properties

Property Name

Description

CommandText

Gets or sets the SQL statement or stored procedure to execute at the data source

CommandTimeout

Gets or sets the wait time before terminating an attempt to execute a command and generating an error

CommandType

Gets or sets a value indicating how the CommandText property is interpreted

Connection

Gets or sets the OleDbConnection or SqlConnection used by this instance of the OleDbCommand or SqlCommand

DesignTimeVisible

Gets or sets a value indicating whether the command object should be visible in a customized Windows Forms Designer control.

Parameters

Gets the OleDbParameterCollection or SqlParameterCollection

Transaction

Gets or sets the transaction in which the OleDbCommand or SqlCommand executes

UpdatedRowSource

Gets or sets how command results are applied to the DataRow when used by the Update method of the DataAdapter

After you set up the Command object and specify a SQL statement or stored procedure name in the CommandText property, you call one of the methods listed in Table 10.3 to execute your SQL statement against the database.

Table 10.3. Execute Methods of the SqlCommand and OleDbCommand Classes

Method Name

Description

ExecuteReader

Executes commands that return rows. For increased performance, ExecuteReader invokes commands using the Transact-SQL sp_executesql system stored procedure. As a result, ExecuteReader might not have the desired effect if used to execute commands such as Transact-SQL SET statements.

ExecuteNonQuery

Executes commands such as Transact-SQL INSERT, DELETE, UPDATE, and SET statements.

ExecuteScalar

Retrieves a single value from a database. This does not include aggregate values.

ExecuteXmlReader (SQL Server Only)

Sends the CommandText to the Connection and builds an XmlReader object. You can also include FOR XML statements when using a Transact-SQL statement with SQL Server.

Each of the methods of the Command object gives you a different type of action based on the requirements.

To read the data after you executed a Command with ExecuteReader, you create a DataReader object that holds the data returned from the database. The DataReader comes in two flavors, SqlDataReader and OleDbDataReader, and you choose one or the other depending on the type of database you want to access.

To see how this all works, Listing 10.1 demonstrates how to connect to a database, how to use the Command object, and how to read data from a DataReader object.

Example 10.1. Using Connection, Command, and DataReader Objects to Retrieve Data

vbnet_icon.gif
Dim cn As New SqlConnection( _
   "Server=(local)\NetSDK;DataBase=pubs" _
   & "Integrated Security=SSPI")

        ' Create a SqlDataReader object
        Dim dr As SqlDataReader

        ' Create a new SqlCommand object
        Dim cmd As New SqlCommand()

        ' Set the Select statement in the CommandText property and
        ' set the Connection property to the "cn" SqlConnection object
        ' you just created
        With cmd
            .CommandText = "Select au_lname, au_fname from Authors"
            .Connection = cn
        End With

        ' Open the Connection
        cn.Open()

        ' Call the ExecuteReader method of the Command object
        dr = cmd.ExecuteReader(CommandBehavior.CloseConnection)

        ' Use this for concatenating the data from the database
        Dim strName As String

        ' Call the Read method of the DataReader to loop thru the records
        While dr.Read
            ' Add the items to the ListBox1 control
            strName = dr("au_lname") & ", " & dr("au_fname")
            MessageBox.Show(strName)
        End While

        ' Close the connection
        cn.Close()

c_icon.gif
SqlConnection cn = new SqlConnection
  (@"Server=(local)\NetSDK;DataBase=pubs;Integrated Security=SSPI");

// Create a SqlDataReader object
SqlDataReader dr;

// Create a new SqlCommand object
SqlCommand cmd = new SqlCommand();

// Set the Select statement in the CommandText property and
// set the Connection property to the "cn" SqlConnection object
// you just created

cmd.CommandText = "Select au_lname, au_fname from Authors";
cmd.Connection = cn;

// Open the Connection
cn.Open();

// Call the ExecuteReader method of the Command object
dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);

// Use this for concatenating the data from the database
string strName;

// Call the Read method of the DataReader to loop thru the records
while (dr.Read())
   {
     // Add the items to the ListBox1 control
     strName = dr.GetString(0) + ", " + dr.GetString(1);
     MessageBox.Show(strName);
     listBox1.Items.Add(strName);
    }

// Close the Connection object
cn.Close();

After you have called the ExecuteReader method, you use the Read method of the DataReader class to loop through the records. Each time a record is read, the position in the Reader is advanced to the next record. This makes it easy to use the While statement to read each row. The Read method returns a False value when there are no more records to read, and your code execution continues after the While loop. Remember, a DataReader is a forward-only set of records, so you can't move backward in the DataReader.

You can also implement other looping techniques for reading data from a DataReader, as the following Visual Basic .NET code demonstrates:

vbnet_icon.gif
Do Until dr.Read = False
        ' do something with the data
Loop

If you compare the Visual Basic .NET and C# code for Listing 10.1, you'll notice a difference in the way the actual data is retrieved from the current record on the Read method of the DataReader. The Visual Basic .NET code uses the actual field name, and the C# code uses the GetString method with the ordinal position of the field you're attempting to access. When reading data with a SQLDataReader, you have different methods of accessing the specific data type in the field of the current row. Table 10.4 is a very compact list of some of the methods in the SqlDataReader class that get values based on data type.

Table 10.4. Methods of the SqlDataReader Class

Method Name

Description

GetSqlBinary

Gets the value of the specified column as a SqlBinary

GetSqlBoolean

Gets the value of the specified column as a SqlBoolean

GetSqlByte

Gets the value of the specified column as a SqlByte

GetSqlDateTime

Gets the value of the specified column as a SqlDateTime

GetSqlDecimal

Gets the value of the specified column as a SqlDecimal

GetSqlDouble

Gets the value of the specified column as a SqlDouble

GetSqlGuid

Gets the value of the specified column as a SqlGuid

GetSqlInt16

Gets the value of the specified column as a SqlInt16

GetSqlInt32

Gets the value of the specified column as a SqlInt32

GetSqlInt64

Gets the value of the specified column as a SqlInt64

GetSqlMoney

Gets the value of the specified column as a SqlMoney

GetSqlSingle

Gets the value of the specified column as a SqlSingle

GetSqlString

Gets the value of the specified column as a SqlString

There are many other methods to retrieve all the data types for SQL Server and OLE DB data sources. It isn't important to list them all here. When you're writing the code in the Visual Studio .NET integrated development environment (IDE), you get the list of possible members for the DataReader class. You'll know if you're using the wrong method when an exception occurs. A safe bet is to use either the numeric ordinal position of the data in the row with the GetString method, or the field name and put the field data into a string. You can then use the System.Convert class to manipulate the data. There's some overhead in doing that, but if you aren't sure of the data type or how to handle it, you can still get the data you need.

Using ExecuteNonQuery with a Command Object

The ExecuteNonQuery method is used when you aren't returning any data, as in the case of an Insert, Update, or Delete. Listing 10.2 demonstrates the use of ExecuteNonQuery using a Command object and a DataReader.

Example 10.2. Using ExecuteNonQuery with a Command Object

vbnet_icon.gif
Sub DoNonQuery()

    Dim cn As New SqlConnection( _
       "Server=(local)\NetSDK;DataBase=pubs" _
       & "Integrated Security=SSPI")


    Dim cmd As New SqlCommand()

    With cmd
        .CommandText = "Delete from Authors where au_lname = 'Smith'"
        .Connection = cn
        .CommandType = CommandType.Text
    End With

    Try
        cn.Open()
        cmd.ExecuteNonQuery()

    Catch ex As Exception

        MessageBox.Show(ex.Message)

    Finally

        If cn.State = ConnectionState.Open Then
            cn.Close()
        End If

    End Try

End Sub

c_icon.gif
private void DoNonQuery()
   {
      SqlConnection cn = new SqlConnection
       (@"Server=(local)\NetSDK;DataBase=pubs;Integrated Security=SSPI");
      SqlCommand cmd = new SqlCommand();

      cmd.CommandText = "Delete from Authors where au_lname = 'Smith'";
      cmd.Connection = cn;
      cmd.CommandType = CommandType.Text ;

      try
         {
            cn.Open();
            cmd.ExecuteNonQuery();
         }
         catch (Exception ex)
         {
            MessageBox.Show(ex.Message);
         }
         finally
         {
            if (cn.State == ConnectionState.Open)
            {
               cn.Close();
            }
         }
    }

The code in Listing 10.2 is almost identical to the code in Listing 10.1. You created a Connection object, a Command object, and then executed the Command. The difference is in the type of SQL statement. When you perform an Insert, Update, or Delete on a database, you don't expect a result set back. By calling the ExecuteNonQuery method, you're saving resources on the server. Because no data is coming back, there's no need to call the ExecuteReader method to hold the returning data stream.

You also check the State property of the Connection object. This is a safe way to close the Connection if it's open. By wrapping this code in a try/catch block, you catch any error that might occur when you open the connection and execute the command. The finally block makes sure that the connection is closed when you're done with it.

Share ThisShare This

Informit Network