In the past two days, we have reconstructed the previous system. In the past, after an SQL exception was found at the data layer, it was processed locally to jump to the error page. The problem is solved at the data layer. Code Only functions related to pages requested by users can be called. The entire system also includes a Windows service project, even if a website project contains a background working thread to process some complex requests asynchronously, they also need to use the data layer. Next, we will provide the reconstruction steps for exception handling:
1. Create your own exception class. One thing is confusing. If I use sqlcommand to execute a query or update, the operation fails for various reasons, and a sqlexception is thrown, therefore, sqlexception should contain an attribute to print the query or update SQL command text. Personally, I think this is the most helpful information for developers. Although the call stack is provided in the exception, you can help me locate the data layer, logic layer, or display Layer Method of the error, but view Source code Find out whether the efficiency of statements related to database operations is too low. But I haven't found it for a long time. Can anyone tell me if they know it? If this property does not exist, why? My own exception class is very simple. Except for an sqlexception object, it is a text that represents SQL commands. The Code is as follows: 1 Public Class Sqltextexception: exception
2 {
3 Private Sqlexception baseexception = Null ;
4 Private String Sqltext = Null ;
5
6 Public Sqltextexception (sqlexception e, String SQL)
7 {
8Baseexception=E;
9Sqltext=SQL;
10}
11
12 Public Sqlexception baseexception
13 {
14 Get
15 {
16ReturnBaseexception;
17}
18 }
19
20 Public String sqltext
21 {
22 Get
23 {
24ReturnSqltext;
25}
26 }
27 }
2. Next, the SQL exception is intercepted at the relevant position on the data layer and encapsulated as sqltextexception type to continue to be thrown. An example of a method on the data layer is as follows:1 Public Object executescalar ( String Cmdtext, sqlparameter [] sqlparams)
2 {
3 If (Plain text = Null )
4 Return Null ;
5
6 Object result = Null ;
7 Sqlcommand command = This . Preparecommand (plain text, sqlparams );
8
9 Try {
10Connection. open ();
11Result=Command. executescalar ();
12}
13 Catch (Sqlexception E) {
14Sqltextexception Mye= NewSqltextexception (E, plain text );
15ThrowMye;
16}
17 Finally {
18Connection. Close ();
19}
20 Return Result;
21 }
3. The exception is created and thrown from the data layer. The next step is to handle the exception. As mentioned at the beginning of the article, the data layer will be used in two runtime environments, namely the synchronous web environment, which has three characteristics: (1)Program(2) The current thread is located in the thread pool managed by w3wp worker process. (3) The user is waiting for the page to be refreshed on the client. In another running environment, the code is either run in the background of the server (Windows Service), or the code is processed by another working thread in the background (task queue ), we are collectively referred to as a non-Web environment. The two environments are described below.
The synchronization web environment plays a major role in the entire system. If exceptions are captured and processed in all methods that may throw exceptions, the workload will be huge. Fortunately, Asp. net has defined a good Exception Handling structure for us (For details, refer to msdn). We can at a certain time point (specifically, the page_error event and application_error event) unprocessed exceptions on the page or the entire application (when an exception is thrown, the CLR will traverse the entire call stack up to view catch blocks that match the type of the thrown exception object; if such a catch block is not found, an unhandled exception occurs. Finally, I implemented the application_error event, that is, add the following code segment to global. ascx:
1 Void Application_error ( Object Sender, eventargs E)
2 {
3 Exception objerr = Server. getlasterror (). getbaseexception ();
4 Gea52.rule. sqlbase. sqltexception myexp = Objerr As Gea52.rule. sqlbase. sqltextexception;
5 If (Myexp ! = Null )
6 {
7 String Err = " The SQL statement that causes the error is \ n. " + Myexp. sqltext + " \ N; error message returned by the system: " + Myexp. baseexception. message;
8 Server. clearerror ();
9 Gea52.rule. commonrule. showerror (ERR );
10 }
11 Else
12 {
13 String Err = " Capture exceptions in application_error: \ n " +
14 " Error in: " + Request. url. tostring () +
15 " \ Nerror message: " + Objerr. Message. tostring () +
16 " \ Nstack trace1: " + Objerr. stacktrace. tostring ();
17
18 Server. clearerror ();
19 Gea52.rule. commonrule. showerror (ERR );
20 }
21 }
The non-web environment is not so lucky, and I have not been able to find a unified location for unhandled exception handling (which brother knows, but I hope you will not be able to tell me ). Fortunately, this part of code is not much. I caught exceptions in some major method calls and stored the caught exceptions in the database (the errorlog table is created in the database, and the table contains message, source, targetsite, stacktrace, and other columns are used to record the main attributes of an exception.