Working with Connection Object Events

Một phần của tài liệu Beginning C# 2005 Databases From Novice to Professional phần 8 doc (Trang 43 - 52)

The connection object has two events: StateChangeand InfoMessage. Let’s look at these in more detail.

Using the StateChange Event

The connection object raises the StateChangeevent when the state of the connection changes. The event handler receives a StateChangeEventArgsobject, which you can exam- ine for detailed information about the event. For example, it has OriginalStateand CurrentStateproperties that you can access to find out the state of the connection object before and after a change.

Try It Out: Writing the Connection.StateChange Event

You’ll now see how this event is handled. You’ll open a connection to the Northwind data- base, retrieve one row from the Customerstable, and close the connection. Then you’ll write an event handler to notify you of when the connection state changes:

1. Create a new Windows Application project named Chapter15. When Solution Explorer opens, save the solution.

2. Rename the Chapter15project AdoNetEvents.

3. Change the Textproperty of Form1to ADO.NET Events.

4. Add four buttons, a label, and a list box to the form, as shown in Figure 15-1.

5. Add a usingdirective to Form1.csfor the System.Data.SqlClientnamespace.

6. Insert the code in Listing 15-1 into the click event handler for the first button.

Listing 15-1.button1_Click() // create connection

SqlConnection conn = new SqlConnection(@"

data source = .\sqlexpress;

integrated security = true;

database = northwind

");

Figure 15-1.ADO.NET Events form

// create command

SqlCommand cmd = new SqlCommand();

cmd.CommandText = @"

select top 1 customerid, companyname from

customers

";

cmd.Connection = conn;

// delegate the StateChange event to the ConnStateChange function conn.StateChange += new StateChangeEventHandler(ConnStateChange);

try {

listBox1.Items.Clear();

// open connection - ConnStateChange event will be fired conn.Open();

// create data reader

SqlDataReader dr = cmd.ExecuteReader();

// display rows in list box while(dr.Read())

{

listBox1.Items.Add(dr.GetString(0) + "-" + dr.GetString(1));

} }

catch(SqlException e1) {

MessageBox.Show (e1.Message);

} finally {

// close connection - ConnStateChange event will be fired conn.Close();

}

7. Add the method in Listing 15-2 to class Form1.cs.

Listing 15-2.ConnStateChange()

private void ConnStateChange(object sender, StateChangeEventArgs ev) {

// Event handler for the StateChange Event

listBox1.Items.Add("---");

listBox1.Items.Add("Entering StateChange EventHandler");

listBox1.Items.Add("Sender = " + sender.ToString());

listBox1.Items.Add("Original State = " + ev.OriginalState.ToString());

listBox1.Items.Add("Current State = " + ev.CurrentState.ToString());

listBox1.Items.Add("Exiting StateChange EventHandler");

listBox1.Items.Add("---");

}

8. Build and run the solution with Ctrl+F5. Click the Connection StateChange Event button. You’ll see the results in Figure 15-2.

Notice the values of the Original Stateand Current Stateproperties before and after the data displays. This example shows that as the connection state changes, the event handler takes over and handles the event.

Figure 15-2.Displaying StateChange Event information

How It Works

You use a query that selects one row from the Customerstable:

// Create command

SqlCommand cmd = new SqlCommand();

cmd.CommandText = @"

select top 1 customerid, companyname from

customers

";

cmd.Connection = conn;

Next, you specify the event handler for the StateChangeevent using the +=operator:

// delegate the StateChange event to the ConnStateChange function conn.StateChange += new StateChangeEventHandler(ConnStateChange);

The location in your code where you specify the event handler is important. In this case, since you want to capture the connection’s StateChangeevent, you specify the dele- gate before you actually open the connection.

You then write the event handler. Earlier, you specified ConnStateChangeas the name of the method that will handle the event. The StateChangeEventHandlerdelegate provides objects with information about the event: the senderobject and the

StateChangeEventArgsobject. The StateChangeevent provides the delegate with these objects, and the delegate gives the event handler these objects so the event handler can handle the event appropriately. That’s why the ConnStateChangeevent handler has the same parameters as the StateChangeEventHandler.

You display information each time the handler is called—that is, each time the connection undergoes a state change:

private void ConnStateChange(object sender, StateChangeEventArgs ev) {

// Event handler for the StateChange Event

listBox1.Items.Add("---");

listBox1.Items.Add("Entering StateChange EventHandler");

listBox1.Items.Add("Sender = " + sender.ToString());

listBox1.Items.Add("Original State = " + ev.OriginalState.ToString());

listBox1.Items.Add("Current State = " + ev.CurrentState.ToString());

listBox1.Items.Add("Exiting StateChange EventHandler");

listBox1.Items.Add("---");

}

This makes it clear when the execution enters and leaves the event handler. You also see that the senderobject is the connection. When the connection is opened, its current state is Openand its original state is Closed. When the connection is closed, the current state is Closedand the original state is Open.

This example runs pretty well, and you can see what’s happening, but in a real-life application, why would users care to be notified if a connection is open or closed? All they need is to see the data. One way to use the StateChangeevent is to keep track of how many times connections are established and keep a running total. Based on this, you can charge users a fee per connection. (Of course, this is a rudimentary way of charging a fee, and you’ll have to figure in other factors.) Another way to use this event would be to keep track of how much time a user has had a connection open and charge based on this.

Using the InfoMessage Event

TheInfoMessageevent is raised by the connection when the database gives out informa- tion messages. Information messages aren’t error messages from the database. They’re warning and informational messages issued by the database. In the case of SQL Server, any message with a severity of ten or less is considered informational and would be cap- tured with the InfoMessageevent.

The InfoMessageevent handler receives an InfoMessageEventArgsobject that contains a collection of the messages from the data source in its Errorscollection property. The Errorobjects in this collection are of type SqlErrorand can be queried for information such as the number, the source, the message, and the exact line number in the stored procedure where this message originated from, among others. Let’s run a query and a T-SQL PRINTstatement. You’ll capture this event and query the information in the Errors collection.

Try It Out: Writing the Connection.InfoMessage Event

To write the Connection.InfoMessageevent, follow these steps:

1. Insert the code in Listing 15-3 into the click event handler for the second button.

Listing 15-3.button2_Click() // create connection

SqlConnection conn = new SqlConnection(@"

data source = .\sqlexpress;

integrated security = true;

database = northwind

");

// delegate the InfoMessage event to the ConnInfoMessage method conn.InfoMessage += new SqlInfoMessageEventHandler(ConnInfoMessage);

// delegate the StateChange event to the ConnStateChange function conn.StateChange += new StateChangeEventHandler(ConnStateChange);

// create command

SqlCommand cmd = new SqlCommand();

cmd.CommandText = @"

select top 2 customerid from customers

";

cmd.Connection = conn;

try {

// clear list box listBox1.Items.Clear();

// open connection conn.Open();

// create data reader

SqlDataReader rdr = cmd.ExecuteReader();

while(rdr.Read()) {

listBox1.Items.Add(rdr.GetString(0));

}

rdr.Close();

// execute a PRINT statement cmd.CommandText = @"

print 'Get CustomerId for all customers'

";

cmd.ExecuteNonQuery();

}

catch(SqlException ex)

{

MessageBox.Show (ex.Message);

} finally {

// close connection conn.Close();

}

2. Add the method in Listing 15-4 to class Form1.cs.

Listing 15-4.ConnInfoMessage()

private void ConnInfoMessage(object sender, SqlInfoMessageEventArgs ev) {

foreach (SqlError err in ev.Errors) {

listBox1.Items.Add("---");

listBox1.Items.Add("Entering InfoMessage Event Handler");

listBox1.Items.Add("Source- " + err.Source);

listBox1.Items.Add("State- " + err.State);

listBox1.Items.Add("Number- " + err.Number);

listBox1.Items.Add("Procedure- " + err.Procedure);

listBox1.Items.Add("Server- " + err.Server);

listBox1.Items.Add("Message- " + err.Message);

listBox1.Items.Add("Exiting InfoMessage Event Handler");

listBox1.Items.Add("---");

} }

3. Build and run the solution with Ctrl+F5. Click the Connection InfoMessage Event button. You’ll see the results shown in Figure 15-3. Scroll down to see how all the information is displayed.

How It Works

After creating a connection object, you specify the CnInfoMessagefunction as the EventHandlerfor the InfoMessageevent:

// delegate the InfoMessage event to the ConnInfoMessage method conn.InfoMessage += new SqlInfoMessageEventHandler(ConnInfoMessage);

You also captured the StateChangeevent by using the same EventHandleryou used before.

// delegate the StateChange event to the ConnStateChange function conn.StateChange += new StateChangeEventHandler(ConnStateChange);

Then you execute a query, get the CustomerIdsof two employees, and add them to the list box:

// create command

SqlCommand cmd = new SqlCommand();

cmd.CommandText = @"

select top 2 customerid from customers

";

Then you execute a PRINTstatement against the database. You use the

ExecuteNonQuerymethod of the command object, since the PRINTstatement doesn’t return any rows:

Figure 15-3.Displaying InfoMessage Event information

// execute a PRINT statement cmd.CommandText = @"

print 'Get CustomerId for all customers'

";

cmd.ExecuteNonQuery();

The EventHandlermethod connInfoMessageis written with the same signature as the delegate SqlInfoMessageEventHandler. The two arguments are the senderobject and the SqlInfoMessageEventArgsobject, which contains information about the event. You then loop through the Errorscollection of the object and list several pieces of information about the message itself:

private void ConnInfoMessage(object sender, SqlInfoMessageEventArgs ev) {

foreach (SqlError err in ev.Errors) {

listBox1.Items.Add("---");

listBox1.Items.Add("Entering InfoMessage Event Handler");

listBox1.Items.Add("Source- " + err.Source);

listBox1.Items.Add("State- " + err.State);

listBox1.Items.Add("Number- " + err.Number);

listBox1.Items.Add("Procedure- " + err.Procedure);

listBox1.Items.Add("Server- " + err.Server);

listBox1.Items.Add("Message- " + err.Message);

listBox1.Items.Add("Exiting InfoMessage Event Handler");

listBox1.Items.Add("---");

} }

Một phần của tài liệu Beginning C# 2005 Databases From Novice to Professional phần 8 doc (Trang 43 - 52)

Tải bản đầy đủ (PDF)

(52 trang)