Microsoft enterprise database 5.0 learning path-Step 3: Add exception handling to the project (record to the database using custom extension)

Source: Internet
Author: User
Tags mscorlib log4net

In the previous article: [entlib] how to learn from Microsoft enterprise database 5.0-Step 2: using the vs2010 + data access module to build a multi-database project, we have set up the overall multi-database environment of the project, implemented multi-database access for the project, but the most important exception handling in the project was not deployed, today, we will use the exception handling + logging module in the Enterprise Library to add Exception Handling and exception logging to the project.

(Note: For the basic concepts related to the exception handling and logging modules, you can view the two articles about terrylee's exception handling and log detection)

First of all, let's talk about the personal feeling of the logging module of the enterprise database. I feel that the log records of the enterprise database are too cumbersome and difficult to customize. I cannot meet my own requirements through simple configuration, the logging module in the enterprise database can record a lot of information as follows:

Timestamp: 3:16:39

Message: handlinginstanceid: 669fed01-a758-434b-896e-a8e25ebf8c9b
An exception of Type 'System. exception' occurred and was caught.
----------------------------------------------------------------
06/12/2010 11:16:39
Type: system. exception, mscorlib, version = 4.0.0.0, culture = neutral, publickeytoken = b77a5c561934e089
Message: Test
Source: entlibstudy. helper
Help link:
Data: system. Collections. listdictionaryinternal
Targetsite: system. String test ()
Stack trace: In entlibstudy. helper. basepage. Test (), F: \ entlibstudy \ helper \ basepage. CS: Row 87
In entlibstudy. helper. basepage. <page_load> B _ 0 () Location F: \ entlibstudy \ helper \ basepage. CS: Row 81
In Microsoft. Practices. enterpriselibrary. exceptionhandling. exceptionmanagerimpl. Process [tresult] (func '1 action, tresult defaultresult, string policyname)

N rows are omitted below ......

Many of the information is not what I want,All I want is the error message, the time when the exception occurred, and the location where the exception occurred, so that we can debug and check the source when the exception occurred.(These abnormal information in the enterprise database may be more useful, but I personally think it will often interfere with us), so we only need a few useful information, suchMessage, timestamp, stack trace, and severity are enough.So I made a deal, that is, using the custom mermertracelistener provided by the logging module in the Enterprise Library to implement the functions we need.

First, create an exception log record table (SQLite version)

CREATE TABLE [ExceptionLog] (    [Id] integer PRIMARY KEY AUTOINCREMENT NOT NULL,    [Message] nvarchar(1024) NOT NULL,    [LogDate] nvarchar(1024) NOT NULL,    [ExceptionLevel] nvarchar(32) NOT NULL,    [Exception] ntext NOT NULL)

I have compiled a class that inherits from customtracelistener and rewritten the record method. The specific code is as follows:

Using system; using system. collections. generic; using system. data; using system. data. common; using system. diagnostics; using system. globalization; using system. LINQ; using system. text; using Microsoft. practices. enterpriselibrary. common. configuration; using Microsoft. practices. enterpriselibrary. data; using Microsoft. practices. enterpriselibrary. logging; using Microsoft. practices. enterpriselibrary. logging. configuration; using Microsoft. practices. enterpriselibrary. logging. formatters; using Microsoft. practices. enterpriselibrary. logging. tracelisteners; namespace entlibstudy. helper. entlibextension. predictionextension {[configurationelementtype (typeof (customtracelistenerdata)] public class exceptionmermerlistener: customtracelistener {string writelogsql = string. empty; database; Exception ex; Public exceptionmermerlistener (): Base () {database = dbhelper. createdatabase ();} public override void tracedata (traceeventcache eventcache, string source, traceeventtype eventtype, int ID, object data) {If (this. filter = NULL) | this. filter. shouldtrace (eventcache, source, eventtype, ID, null, null, Data, null) {If (data is logentry) {logentry = data as logentry; executesql (logentry );} else if (data is string) {write (data as string);} else {base. tracedata (eventcache, source, eventtype, ID, data) ;}} public override void write (string message) {executewritelogsql (traceeventtype. information, datetime. now, message, database);} public override void writeline (string message) {write (Message );} /// <summary> /// Execute SQL // </Summary> /// <Param name = "logentry"> log object </param> private void executesql (logentry logentry) {using (dbconnection connection = database. createconnection () {try {connection. open (); Using (dbtransaction transaction = connection. begintransaction () {try {executewritelogsql (logentry, database, transaction); transaction. commit ();} catch {transaction. rollback (); throw ;}} finally {connection. close ();}}} /// <summary> /// execute the write log database statement /// </Summary> /// <Param name = "severity"> exception level </param> // /<Param name = "message"> message </param> // <Param name = "DB"> database instance for storing logs </param> private void executewritelogsql (traceeventtype severity, datetime timestamp, string message, database dB) {writelogsql = (string) This. attributes ["writelogsql"]; dbcommand cmd = dB. getsqlstringcommand (writelogsql); string exceptionmessage = utils. getbetweenstring (message, "message:", "Source:", 9); string exceptioninfo = utils. getbetweenstring (message, "stack trace:", "Additional Info:", 13); dB. addinparameter (CMD, "@ message", dbtype. string, exceptionmessage); dB. addinparameter (CMD, "@ logdate", dbtype. datetime, timestamp); dB. addinparameter (CMD, "@ level", dbtype. string, message); dB. addinparameter (CMD, "@ exception", dbtype. string, exceptioninfo); dB. executenonquery (CMD );} /// <summary> /// execute the write log database statement /// </Summary> /// <Param name = "logentry"> log object </param> // /<Param name = "DB"> database instance for storing logs </param> // <Param name = "transaction"> transaction object </param> private void executewritelogsql (logentry logentry, database dB, dbtransaction transaction) {writelogsql = (string) This. attributes ["writelogsql"]; dbcommand cmd = dB. getsqlstringcommand (writelogsql); string exceptionmessage = utils. getbetweenstring (logentry. message, "message:", "Source:", 9); string exceptioninfo = utils. getbetweenstring (logentry. message, "stack trace:", "Additional Info:", 13); dB. addinparameter (CMD, "@ message", dbtype. string, exceptionmessage); dB. addinparameter (CMD, "@ logdate", dbtype. datetime, logentry. timestamp. tolocaltime (); dB. addinparameter (CMD, "@ level", dbtype. string, logentry. loggedseverity); dB. addinparameter (CMD, "@ exception", dbtype. string, exceptioninfo); dB. executenonquery (CMD, transaction );}}}

The default database object of the configuration file is obtained during class initialization. The executesql method is called to execute exception log insertion by rewriting the tracedata method.

The executewritelogsql method contains the following code:

 

writeLogSQL = (string)this.Attributes["writeLogSQL"];

This code obtains the configured execution SQL statement from the attributes of the listener in the configuration file (this is different from the logging method of the database in the logging module, instead, use the configured SQL statement, because this project is oriented to multiple databases, not all databases have stored procedures, such as SQLite ), the specific configuration information is as follows:

The configuration file is created in the following two steps:

1. Add an exception handle module in the configuration tool of the enterprise database, add a policy named exception policy, and add the exception type for this policy. By default, I select all Exception types ), post handle action: policyrethow (for methods that do not understand post handle action, see the following explanation)

Posthandlingaction determines what activity will take place after the exception handling link is complete. By default, posthandlingaction is set to policyrethrow.
None: The Application Block executes all the processing programs for this exception, and then returns false to the application at the call point of the handleexception method. The application checks this value to continue running.
Notifyrethrow: The Application Block executes all the processing programs for this exception, and then returns true to the application at the call point of the handleexception method. When the application checks this value, the original exception is thrown again.
Thrownewexception: The Application Block executes all the processing programs for this exception, and then throws an exception after all the processing programs run.

2. Create a processing method for the exception policy. Here, select Loggin exception handler (At the same time of creation, the configuration tool will automatically create the logging module and automatically create a log category: General. However, the default listener for this log category is event log, is recorded in system events.), Then we create a customertracelistenerFrom file-> The DLL of the custom listener.

Here I encountered a problem that I added customertracelistener. In the dialog box, I click from file and select the DLL where the custom listener I wrote is located. Unfortunately, there is no response, I don't know what to do in the DLL, so I can only use the old method: hand-writing configuration file

First, let's take a look at the configuration information of the exception handle module:

<exceptionHandling>    <exceptionPolicies>      <add name="ExceptionPolicy">        <exceptionTypes>          <add name="All Exceptions" type="System.Exception, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"            postHandlingAction="NotifyRethrow">            <exceptionHandlers>              <add name="Logging Exception Handler" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"                logCategory="General" eventId="100" severity="Error" title="Enterprise Library Exception Handling"                formatterType="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.TextExceptionFormatter, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling"                priority="0" />            </exceptionHandlers>          </add>        </exceptionTypes>      </add>    </exceptionPolicies>  </exceptionHandling>

 

Next, configure the Log Module. In the Log Module, I have configured three listener. M trace listener is the custom exception log record,Event Log listener (System Log Record)AndRolling flat file trace listener (text file record, rollback record by day)The reason why the general log category cannot be recorded when the general log category cannot be recorded is normal is that the exception log is saved to the database by default, but if there is a problem in the database, or when the link is closed, exceptions cannot be recorded normally, so:

<loggingConfiguration name="" tracingEnabled="true" defaultCategory="General">    <listeners>      <add listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.CustomTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging"        writeLogSQL="insert into ExceptionLog(Message,LogDate,ExceptionLevel,Exception) values(@Message,@LogDate,@Level,@Exception)"        type="EntLibStudy.Helper.EntLibExtension.ExceptionExtension.ExceptionCustomerListener, EntLibStudy.Helper, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"        traceOutputOptions="None" name="Custom Trace Listener" initializeData=""        formatter="Text Formatter" />      <add name="Event Log Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FormattedEventLogTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"        listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FormattedEventLogTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"        source="Enterprise Library Logging" formatter="Text Formatter"        log="" machineName="." traceOutputOptions="None" />      <add name="Rolling Flat File Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.RollingFlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"        listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.RollingFlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"        fileName="rolling.log" formatter="Text Formatter" rollInterval="Day" />    </listeners>    <formatters>      <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"        template="Timestamp: {timestamp}{newline}Message: {message}{newline}Category: {category}{newline}Priority: {priority}{newline}EventId: {eventid}{newline}Severity: {severity}{newline}Title:{title}{newline}Machine: {localMachine}{newline}App Domain: {localAppDomain}{newline}ProcessId: {localProcessId}{newline}Process Name: {localProcessName}{newline}Thread Name: {threadName}{newline}Win32 ThreadId:{win32ThreadId}{newline}Extended Properties: {dictionary({key} - {value}{newline})}"        name="Text Formatter" />    </formatters>    <categorySources>      <add switchValue="All" name="General">        <listeners>          <add name="Custom Trace Listener" />        </listeners>      </add>    </categorySources>    <specialSources>      <allEvents switchValue="All" name="All Events" />      <notProcessed switchValue="All" name="Unprocessed Category" />      <errors switchValue="All" name="Logging Errors & Warnings">        <listeners>          <add name="Event Log Listener" />          <add name="Rolling Flat File Trace Listener" />        </listeners>      </errors>    </specialSources>  </loggingConfiguration>

 

After the configuration is complete, we can write code and perform exception Control on the page.

In ASP. in. net, there are four main types of exception handling. The execution sequence is: page_error event> errorpage attribute> application_error event> <customerrors>. Here we use page_error, since I have created a basepage in this project, all the pages inherit this page, so I only need to compile the page_error event in this page:

Protected void page_error (Object sender, eventargs e) {// obtain the latest exception information var EX = server. getlasterror (); // handle handleexception (ex, "exceptionpolicy"); // clear the abnormal server. clearerror ();} /// <summary> /// Exception Handling Method /// </Summary> /// <Param name = "ex"> exception information </param> /// <param name = "policy"> Exception Handling Policy </param> protected void handleexception (exception ex, string Policy) {bool rethrow = false; var exmanager = Enterprise Librarycontainer. Current. getinstance <exceptionmanager> (); rethrow = exmanager. handleexception (ex, policy); If (rethrow) {This. redirectpermanent ("~ /Error. aspx ");}}

 

Exmanager. handleexception (ex, Policy) is used to handle exceptions based on the Policy Name. Our exceptionpolicy is used to handle exception logs. It will help us call our customPredictioncustomerlistenerClass for exception logging.

In this way, we have completed the exceptions in the unified capture system. This article also ends here. Thank you for your advice!

 

-------------------------------- Article Extension split line -----------------------------------------------

Of course, the exception handle and logging modules in the Enterprise Library are far more than that. Exception handle also provides exception replacement.(Replace the specified exception with other exception information ),Abnormal Packaging(Package one exception to another)

The logging module provides many record methods, such as text, XML, mail, and message queue. Therefore, we can choose based on our needs.

This article simply expands my actual project requirements, so there may be many shortcomings. You can study and expand according to your own needs, if you have a good way to handle the exception record, let me use it for reference. :)

 

PS: I mentioned in my article that the logging module of the Enterprise Library is too cumbersome. You can refer to my article about how to use log4net to record program exceptions (using SQLite database records and common text records, log4net is a good choice if you only want to record system exceptions, and the configuration is convenient and lightweight, if you want to fully use the functions of the enterprise database, you can still use the exception handle + logging combination.

Note:

1. The MSSQL database is in the database directory (you need to attach the database yourself), and The SQLite database is in the app_data directory of the web directory. Because of the project size, the bin directory of each project has been deleted, if a project cannot be generated, add the DLL of the relevant enterprise library.

2. As Microsoft enterprise database 5.0 is a learning path, this series is intended to introduce the modules of the enterprise database in the form of a small project, so the source code will be updated according to the updates in the series of articles, therefore, the source code cannot be the same as the Code posted in the article.

3. The project development environment is vs2010 + sql2005.

4. Administrator Account: Admin

Password: Admin

Source code: Click to download

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.