Beginning C# 2005 Databases From Novice to Professional phần 8 doc

52 364 0
Beginning C# 2005 Databases From Novice to Professional phần 8 doc

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

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

10. Run the program with Ctrl+F5. Click the ADO.NET Exception-1 button, and you’ll see the message box shown in Figure 13-3. Click OK. 11. When the message box in Figure 13-4 appears, click OK, then close the window. How It Works It would be highly unusual to miss setting the CommandText property. However, this is an expedient way to cause an ADO.NET exception. You specify the command for a stored procedure call, but you don’t specify the stored procedure to call // Specify that a stored procedure is to be executed cmd.CommandType = CommandType.StoredProcedure; // Deliberately fail to specify the procedure // cmd.CommandText = "sp_Select_AllEmployees"; so when you call the ExecuteReader method, you get an exception, as shown in F igure 13-2. Though it’s an unhandled exception, it still gives you an accurate diagnostic ExecuteReader: CommandText property has not been intiailized. and it even gives you the option to continue or quit. However, leaving this decision to users isn’t a very good idea. After seeing what happens without handling the exception, you place the call in a try block: CHAPTER 13 ■ HANDLING EXCEPTIONS 339 Figure 13-3. Handled exception message Figure 13-4. Message from finally block 777Xch13final.qxd 11/18/06 2:36 PM Page 339 try { // Open connection conn.Open(); // Create data reader SqlDataReader dr = cmd.ExecuteReader(); // Close reader dr.Close(); } To handle the exception yourself, you code two catch clauses: catch (System.Data.SqlClient.SqlException ex) { string str; str = "Source:" + ex.Source; str += "\n" + "Exception Message:" + ex.Message; MessageBox.Show (str, "Database Exception"); } catch (System.Exception ex) { string str; str = "Source:" + ex.Source; str += "\n" + "Exception Message:" + ex.Message; MessageBox.Show (str, "Non-Database Exception"); } In the first catch clause, you specify a database exception type. The second catch clause, which produces the message box in Figure 13-3, is a generic block that catches all types of exceptions. Note the caption of the message box in this catch block. It says Non-Database Exception. Although you may think that a failure to specify a command string is a database exception, it’s actually an ADO.NET exception; in other words, this error is trapped before it gets to the database server. When the button is clicked, since the CommandText property isn’t specified, an excep- tion is thrown and caught by the second catch clause. Even though a catch clause for SqlException is provided, the exception is a System.InvalidOperationException—a com- mon exception thrown by the CLR, not a database exception. The exception message indicates where the problem occurred: in the ExecuteReader method. The finally block checks if the connection is open and, if it is, closes it and gives a message to that effect. Note that in handling the exception, you don’t terminate the application: CHAPTER 13 ■ HANDLING EXCEPTIONS340 777Xch13final.qxd 11/18/06 2:36 PM Page 340 finally { if (conn.State == ConnectionState.Open) { MessageBox.Show ("Finally block closing the connection", "Finally"); conn.Close(); } } Try It Out: Handling an ADO.NET Exception (Part 2) Let’s try another example of an ADO.NET exception. You’ll execute a stored procedure and then reference a nonexistent column in the returned dataset. This will throw an ADO.NET exception. This time, you’ll code a specific catch clause to handle the exception: 1. Use the sp_Select_All_Employees stored procedure you created in Chapter 12. If you haven’t created it already, please go to Chapter 12 and follow the steps in “Try It Out: Creating and Executing a Trivial Stored Procedure.” 2. Insert the code in Listing 13-3 into the body of the button2_Click method. Listing 13-3. button2_Click() // Create connection SqlConnection conn = new SqlConnection(@" data source = .\sqlexpress; integrated security = true; database = northwind "); // Create command SqlCommand cmd = conn.CreateCommand(); // Specify that a stored procedure is to be executed cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "sp_Select_All_Employees"; CHAPTER 13 ■ HANDLING EXCEPTIONS 341 777Xch13final.qxd 11/18/06 2:36 PM Page 341 try { // Open connection conn.Open(); // Create data reader SqlDataReader dr = cmd.ExecuteReader(); // Access nonexistent column string str = dr.GetValue(20).ToString(); // Close reader dr.Close(); } catch (System.InvalidOperationException ex) { string str; str = "Source: " + ex.Source; str += "\n" + "Message: "+ ex.Message; str += "\n" + "\n"; str += "\n" + "Stack Trace: " + ex.StackTrace; MessageBox.Show (str, "Specific Exception"); } catch (System.Data.SqlClient.SqlException ex) { string str; str = "Source: " + ex.Source; str += "\n" + "Exception Message: " + ex.Message; MessageBox.Show (str, "Database Exception"); } catch (System.Exception ex) { string str; str = "Source: " + ex.Source; str += "\n" + "Exception Message: " + ex.Message; MessageBox.Show (str, "Non-Database Exception"); } CHAPTER 13 ■ HANDLING EXCEPTIONS342 777Xch13final.qxd 11/18/06 2:36 PM Page 342 finally { if (conn.State == ConnectionState.Open) { MessageBox.Show ("Finally block closing the connection", "Finally"); conn.Close(); } } ■Tip Testing whether a connection is open before attempting to close it isn’t actually necessary. The Close method doesn’t throw any exceptions, and calling it multiple times on the same connection, even if it’s already closed, causes no errors. 3. Run the program with Ctrl+F5. Click the ADO.NET Exception-2 button, and you’ll see the message box shown in Figure 13-5. Click OK. When the finally block mes- sage appears, click OK, then close the window. 4. F or a quick comparison, now generate a SQL Server exception, an error that occurs within the database. Alter the name of the stored procedure in the code to a name that doesn’t exist within the Northwind database. For example: cmd.CommandText = "sp_Select_No_Employees"; CHAPTER 13 ■ HANDLING EXCEPTIONS 343 Figure 13-5. Handling a specific ADO.NET exception 777Xch13final.qxd 11/18/06 2:36 PM Page 343 5. Run the program with Ctrl+F5. Click the ADO.NET Exception-2 button, and you’ll see the message box shown in Figure 13-6. Click OK. When the finally block mes- sage appears, click OK, then close the window. How It Works First you create the data reader and try to access an invalid column: // Create data reader SqlDataReader dr = cmd.ExecuteReader(); // Access nonexistent column string str = dr.GetValue(20).ToString(); An exception is thrown, because you tried to get the value of column 20, which doesn’t exist. You add a new catch clause to handle this kind of ADO.NET error: catch (System.InvalidOperationException ex) { string str; str = "Source: " + ex.Source; str += "\n" + "Message: "+ ex.Message; str += "\n" + "\n"; str += "\n" + "Stack Trace: " + ex.StackTrace; MessageBox.Show (str, "Specific Exception"); } When an exception of type System.InvalidOperationException is thrown, this catch clause executes, displaying the source, message, and stack trace for the exception. Without this specific catch clause, the generic catch clause would have handled the exception. (Try commenting out this catch clause and reexecuting the code to see which catch clause handles the exception.) CHAPTER 13 ■ HANDLING EXCEPTIONS344 Figure 13-6. Handling a SQL Server exception 777Xch13final.qxd 11/18/06 2:36 PM Page 344 Next, you run the program for a nonexistent stored procedure: // Specify that a stored procedure is to be executed cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "sp_Select_No_Employees"; You catch your (first) database exception with catch (System.Data.SqlClient.SqlException ex) which leads into the next topic: handling exceptions thrown by the database manager. Handling Database Exceptions An exception of type System.Data.SqlClient.SqlException is thrown when SQL Server returns a warning or error. This class is derived from System.SystemException and is sealed so it can’t be inherited, but it has several useful members that you can interrogate to obtain valuable information about the exception. An instance of SqlException is thrown whenever the .NET data provider for SQL Server encounters an error or warning from the database. Table 13-1 describes the prop- erties of this class that provide information about the exception. Table 13-1. SqlException Properties Property Name Description Class Gets the severity level of the error returned from the SqlClient data provider. The severity level is a numeric code that’s used to indicate the nature of the error. Levels 1 to 10 ar e informational errors; 11 to 16 are user-level errors; and 17 to 25 are software or har dware errors. At level 20 or greater, the connection is usually closed. Data Gets a collection of key-value pairs that contain user-defined information. ErrorCode The HRESUL T of the err or . Errors Contains one or more SqlError objects that have detailed information about the exception. This is a collection that can be iterated through. HelpLink The help file associated with this ex ception. InnerException Gets the exception instance that caused the current exception. LineNumber Gets the line number within the Transact-SQL command batch or stored procedure that generated the exception. Message The text describing the exception. Number The number that identifies the type of ex ception. Continued CHAPTER 13 ■ HANDLING EXCEPTIONS 345 777Xch13final.qxd 11/18/06 2:36 PM Page 345 Table 13-1. Continued Property Name Description Procedure The name of the stored procedure that generated the exception. S erver T he name of the computer running the instance of SQL Server that generated t he exception. Source The name of the provider that generated the exception. StackTrace A string representation of the call stack when the exception was thrown. State Numeric error code from SQL Server that represents an exception, warning, or “no data found” message. For more information, see SQL Server Books Online. TargetSite The method that throws the current exception. When an error occurs within SQL Server, it uses a T-SQL RAISERROR statement to raise an error and send it back to the calling program. A typical error message looks like the following: Server: Msg 2812, Level 16, State 62, Line 1 Could not find stored procedure 'sp_DoesNotExist' In this message, 2812 represents the error number, 16 represents the severity level, and 62 represents the state of the error. You can also use the RAISERROR statement to display specific messages within a stored procedure. The RAISERROR statement in its simplest form takes three parameters. The first parameter is the message itself that needs to be shown. The second parameter is the severity level of the error. Any users can use severity levels 11 through 16. They represent messages that can be categorized as information, software, or hardware problems. The third parameter is an arbitrary integer from 1 through 127 that represents information about the state or source of the error. Let’s see how a SQL error, raised by a stored procedure, is handled in C#. You’ll cre- ate a stored procedure and use the following T-SQL to raise an error when the number of orders in the Orders table exceeds ten: if @orderscount > 10 raiserror ( 'Orders Count is greater than 10 - Notify the Business Manager', 16, 1 ) Note that in this RAISERROR statement, you specify a message string, a severity level of 16, and an arbitrary state number of 1. When a RAISERROR statement that you write contains a message string, the error number is given automatically as 50000. When CHAPTER 13 ■ HANDLING EXCEPTIONS346 777Xch13final.qxd 11/18/06 2:36 PM Page 346 SQL Server raises errors using RAISERROR, it uses a predefined dictionary of messages to give out the corresponding error numbers. (See SQL Server Books Online to learn how to add your own messages to SQL Server’s predefined messages.) Try It Out: Handling a Database Exception (Part 1): RAISERROR Let’s raise a database error and handle the exception: 1. Add a button to the Database tab page and change its Text property to Database Exception-1 . Add a label to the right of this button, and change its Text property to Calls a stored procedure that uses RAISERROR. 2. Add a second button to the tab page, and change its Text property to Database Exception-2. Add a label to the right of this button, and change its Text property to Calls a stored procedure that encounters an error. 3. Add a third button to the tab page, and change its Text property to Database Exception-3. Add a label to the right of this button, and change its Text property to Creates multiple SqlError objects. The layout should look like Figure 13-7. 4. U sing SSMSE, create a stored procedure in Northwind named sp_DbException_1, as follo ws: create procedure sp_DbException_1 as set nocount on declare @ordercount int CHAPTER 13 ■ HANDLING EXCEPTIONS 347 Figure 13-7. Database tab page 777Xch13final.qxd 11/18/06 2:36 PM Page 347 select @ordercount = count(*) from orders if @ordercount > 10 raiserror ( 'Orders Count is greater than 10 - Notify the Business Manager', 16, 1 ) 5. Add the code in Listing 13-4 to the button3_Click method. Listing 13-4. button3_Click() // Create connection SqlConnection conn = new SqlConnection(@" data source = .\sqlexpress; integrated security = true; database = northwind "); // Create command SqlCommand cmd = conn.CreateCommand(); // Specify that a stored procedure to be executed cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "sp_DbException_1"; try { // Open connection conn.Open(); // Execute stored procedure cmd.ExecuteNonQuery(); } catch (System.Data.SqlClient.SqlException ex) { string str; str = "Source: " + ex.Source; CHAPTER 13 ■ HANDLING EXCEPTIONS348 777Xch13final.qxd 11/18/06 2:36 PM Page 348 [...]... a transaction to both add a customer to and delete one from the Northwind Customers table Customers has eleven columns, but only two, CustomerID and CompanyName, don’t allow nulls, so we’ll use just those columns for insertion We’ll also use arbitrary customer IDs to make it easy to find the rows we manipulate when viewing customers sorted by ID 1 In SSMSE, create a stored procedure named sp_Trans_Test,... Let’s see a more C#- like alternative Try It Out: Coding a Transaction with the TRY…CATCH Construct Let’s code a transaction to both add a customer to and delete one from the Northwind Customers table Customers has eleven columns, but only two, CustomerID and CompanyName, don’t allow nulls, so we’ll use just those columns for insertion We’ll also use arbitrary customer IDs to make it easy to find the rows... is lengthier than it has to be The biggest changes were moving the statements, including COMMIT, into a TRY block: begin try begin transaction Add a customer insert into customers ( customerid, companyname ) values(@newcustid, @newconame) Save error number set @inserr = @@error if @inserr > @maxerr set @maxerr = @inserr Delete a customer delete from customers where customerid = @oldcustid Save... Exception-2 button You’ll see the message box shown in Figure 13-9 Click OK to close the message box, then OK to close the next one, then close the window Figure 13-9 Stored procedure Database Exception message How It Works The stored procedure tries to insert a new employee into the Employees table: insert into employees ( employeeid, firstname ) values (50, 'Cinderella') 353 777Xch13final.qxd 354 11/ 18/ 06... begin transaction Add a customer insert into customers ( customerid, companyname ) values(@newcustid, @newconame) Save error number set @inserr = @@error if @inserr > @maxerr set @maxerr = @inserr Delete a customer delete from customers where customerid = @oldcustid Save error number set @delerr = @@error if @delerr > @maxerr set @maxerr = @delerr 777Xch14final.qxd 11/ 18/ 06 2:35 PM Page 371 CHAPTER... There’s much more to transactions than we can cover in this chapter, but the following examples will give you a foundation to extrapolate from to handle any combination of operations Try It Out: What Happens When the First Operation Fails In this example, you’ll try to insert an invalid (duplicate) customer and delete a deletable one 1 Run sp_Trans_Test to add customer a and delete customer aa The result... transaction After each statement, you saved the return number for it begin transaction Add a customer insert into customers ( customerid, companyname ) values(@newcustid, @newconame) Save error number set @inserr = @@error if @inserr > @maxerr set @maxerr = @inserr Delete a customer delete from customers where customerid = @oldcustid Save error number set @delerr = @@error if @delerr > @maxerr set @maxerr... 777Xch14final.qxd 11/ 18/ 06 2:35 PM Page 363 CHAPTER 14 s USING TRANSACTIONS begin transaction Add a customer insert into customers ( customerid, companyname ) values(@newcustid, @newconame) Save error number set @inserr = @@error if @inserr > @maxerr set @maxerr = @inserr Delete a customer delete from customers where customerid = @oldcustid Save error number set @delerr = @@error if @delerr > @maxerr set @maxerr... deletion Try It Out: What Happens When the Second Operation Fails In this example, you’ll insert a valid new customer and try to delete an undeletable one 367 777Xch14final.qxd 3 68 11/ 18/ 06 2:35 PM Page 3 68 CHAPTER 14 s USING TRANSACTIONS 1 Run sp_Trans_Test to add customer aaa and delete customer ALFKI The result should appear as in Figure 14-4 Figure 14-4 First operation rolled back 2 In the Messages... you’ll code a C# equivalent of sp_Trans_Try 1 Create a new Windows Application project named Chapter14 When Solution Explorer opens, save the solution 2 Rename the Chapter14 project to AdoNetTransactions and Program1.cs to AdoNetTransactions.cs 3 Change the Text property of Form1 to ADO.NET Transactions 4 Add three labels, three text boxes, and a button to the form as in Figure 14 -8 Figure 14 -8 ADO.NET . exception: 1. Add a button to the Database tab page and change its Text property to Database Exception-1 . Add a label to the right of this button, and change its Text property to Calls a stored procedure. Add a second button to the tab page, and change its Text property to Database Exception-2. Add a label to the right of this button, and change its Text property to Calls a stored procedure. an expedient way to cause an ADO.NET exception. You specify the command for a stored procedure call, but you don’t specify the stored procedure to call // Specify that a stored procedure is to be executed cmd.CommandType

Ngày đăng: 09/08/2014, 14:20

Từ khóa liên quan

Mục lục

  • Beginning C# 2005 Databases: From Novice to Professional

    • Chapter 14 Using Transactions

    • Chapter 15 Working with ADO.NET Events

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

  • Đang cập nhật ...

Tài liệu liên quan