Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇

时间:2022-06-12 22:48:40
  Enterprise Library Step By Step 系列(十二):异常处理应用程序块——进阶篇

作者:Terrylee

一.把异常信息Logging到数据库

在日志和监测应用程序块中,有朋友提意见说希望能够把异常信息Logging到数据库中,在这里介绍一下具体的实现方法。

1.创建相关的数据库环境:

我们可以用日志和监测应用程序块自带的SQL语句来创建相关的数据库环境:

创建数据库:

Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇CREATE   DATABASE   [ Logging ]    ON  (NAME  =  N ' Logging ' , FILENAME  =  N ' C:\Program Files\Microsoft SQL Server\MSSQL\data\Logging.mdf '  , SIZE  =   1 , FILEGROWTH  =   10 % LOG   ON  (NAME  =  N ' Logging_log ' , FILENAME  =  N ' C:\Program Files\Microsoft SQL Server\MSSQL\data\Logging_log.LDF '  , FILEGROWTH  =   10 % )

创建表:

Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇CREATE   TABLE   [ dbo ] . [ Log ]  (
Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    
[ LogID ]   [ int ]   IDENTITY  ( 1 1 NOT   NULL  ,
Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    
[ EventID ]   [ int ]   NULL  ,
Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    
[ Category ]   [ nvarchar ]  ( 64 ) COLLATE SQL_Latin1_General_CP1_CI_AS  NOT   NULL  ,
Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    
[ Priority ]   [ int ]   NOT   NULL  ,
Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    
[ Severity ]   [ nvarchar ]  ( 32 ) COLLATE SQL_Latin1_General_CP1_CI_AS  NOT   NULL  ,
Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    
[ Title ]   [ nvarchar ]  ( 256 ) COLLATE SQL_Latin1_General_CP1_CI_AS  NOT   NULL  ,
Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    
[ Timestamp ]   [ datetime ]   NOT   NULL  ,
Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    
[ MachineName ]   [ nvarchar ]  ( 32 ) COLLATE SQL_Latin1_General_CP1_CI_AS  NOT   NULL  ,
Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    
[ AppDomainName ]   [ nvarchar ]  ( 2048 ) COLLATE SQL_Latin1_General_CP1_CI_AS  NOT   NULL  ,
Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    
[ ProcessID ]   [ nvarchar ]  ( 256 ) COLLATE SQL_Latin1_General_CP1_CI_AS  NOT   NULL  ,
Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    
[ ProcessName ]   [ nvarchar ]  ( 2048 ) COLLATE SQL_Latin1_General_CP1_CI_AS  NOT   NULL  ,
Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    
[ ThreadName ]   [ nvarchar ]  ( 2048 ) COLLATE SQL_Latin1_General_CP1_CI_AS  NULL  ,
Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    
[ Win32ThreadId ]   [ nvarchar ]  ( 128 ) COLLATE SQL_Latin1_General_CP1_CI_AS  NULL  ,
Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    
[ Message ]   [ nvarchar ]  ( 2048 ) COLLATE SQL_Latin1_General_CP1_CI_AS  NULL  ,
Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    
[ FormattedMessage ]   [ ntext ]  COLLATE SQL_Latin1_General_CP1_CI_AS  NULL  
Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇
ON   [ PRIMARY ]  TEXTIMAGE_ON  [ PRIMARY ]
Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇
GO
Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇

创建存储过程:

 1 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇CREATE   PROCEDURE  WriteLog
 2 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇(
 3 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇     @EventID   int
 4 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇     @Category   nvarchar ( 64 ),
 5 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇     @Priority   int
 6 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇     @Severity   nvarchar ( 32 ), 
 7 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇     @Title   nvarchar ( 256 ), 
 8 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇     @Timestamp   datetime ,
 9 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇     @MachineName   nvarchar ( 32 ), 
10 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇     @AppDomainName   nvarchar ( 2048 ),
11 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇     @ProcessID   nvarchar ( 256 ),
12 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇     @ProcessName   nvarchar ( 2048 ),
13 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇     @ThreadName   nvarchar ( 2048 ),
14 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇     @Win32ThreadId   nvarchar ( 128 ),
15 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇     @Message   nvarchar ( 2048 ),
16 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇     @FormattedMessage   ntext
17 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇)
18 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇 AS  
19 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇
20 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇     INSERT   INTO   [ Log ]  (
21 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        EventID,
22 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        Category,
23 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        Priority,
24 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        Severity,
25 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        Title,
26 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇         [ Timestamp ] ,
27 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        MachineName,
28 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        AppDomainName,
29 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        ProcessID,
30 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        ProcessName,
31 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        ThreadName,
32 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        Win32ThreadId,
33 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        Message,
34 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        FormattedMessage
35 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    )
36 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇     VALUES  (
37 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇         @EventID
38 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇         @Category
39 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇         @Priority
40 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇         @Severity
41 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇         @Title
42 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇         @Timestamp ,
43 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇         @MachineName
44 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇         @AppDomainName ,
45 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇         @ProcessID ,
46 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇         @ProcessName ,
47 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇         @ThreadName ,
48 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇         @Win32ThreadId ,
49 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇         @Message ,
50 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇         @FormattedMessage )
51 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇 GO

SQL语句默认的路径为C:\Program Files\Microsoft Enterprise Library\src\Logging\Sinks\Database\Scripts,直接运行CreateLoggingDatabase.cmd即可。

2.运行配置工具,我们创建一个日志和监测应用程序块,并建一个Database Sink,具体的配置方法在日志和监测应用程序块中讲过了,这里就不重复了,我们看一下它的配置:

 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇

注意设置StoredProcNameWriteLog,就是我们刚才创建的存储过程。

3.同时再创建一个Category,起名为DataException,并设置它的SinkDatabase Sink

4.设置Logging HandlerLogCategory为我们刚才创建的DataException,其他的参数暂时默认。

 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇

5.至此配置完成,在程序中我们不需要做任何改动(这就是企业库的配置驱动的思想精妙之处^_^)。

 1 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇 /// <summary>
 2Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        /// 日志策略
 3Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        /// </summary>
 4Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        /// <param name="sender"></param>
 5Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        /// <param name="e"></param>

 6 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇         private   void  btn_Log_Click( object  sender, System.EventArgs e)
 7 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇         {
 8Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇            try
 9Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇            {
10Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇                Exception ex = new Exception();
11Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇                throw ex;
12Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇            }

13Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇            catch(Exception ex)
14Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇            {
15Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇                bool Flag = ExceptionPolicy.HandleException(ex,"Log Policy");
16Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇
17Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇                if(Flag)
18Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇                {
19Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇                    throw;
20Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇                }

21Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇            }

22Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        }

补充一点:在项目中要添加对Microsoft.Practices.EnterpriseLibrary.Logging.Sinks.Database.dll的引用

二.异常的传播机制

异常的传播机制有以下几种:

l        异常自动传播

l        在同一层内部,捕获或者再抛出原有异常

l        捕获,包装和抛出包装后的异常

我们不推荐直接抛出原有异常,因为恶意的用户能够从系统诊断信息中得知应用的详细情况,并从中查找应用的弱点。异常应用程序块提供了一旦配置的Handler执行后,就产生对应的post-handling动作,该动作有如下选项:

None 没有重抛异常的动作。

NotifyRethrow 告诉调用程序:Policy推荐应该重抛异常。

ThrowNewException 在所有的Handler执行后,向调用程序抛出最终异常(并不一定是原始的异常)。


三.异常的格式化

可以格式化任何System.Exception类型的异常

能够用来记录或者显示异常的详细信息

字符型格式化器——TextExceptionFormatter:创建在一个屏幕上,日志中或以其他形式表现的,可以表现异常信息的详细记录

XML格式化器——XMLExceptionFormatter:针对一个异常,创建一个用XML表现形式表现记录,每一个异常的属性,均可以被存储为XML元素。

看一下在Enterprise Library Quick Start中提供的自定义的ExceptionFormatter,实现了TextExceptionFormatter类:

 1 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇 /// <summary>
 2Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    /// Summary description for AppTextExceptionFormatter.
 3Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    /// </summary>    

 4 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇     public   class  AppTextExceptionFormatter : TextExceptionFormatter
 5 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇     {
 6Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        public AppTextExceptionFormatter(TextWriter writer, Exception exception)
 7Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇            : base (writer, exception) 
 8Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇            {
 9Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇            }

10Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        
11Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        protected override void WriteDescription() 
12Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        {
13Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇            // An exception of type {0} occurred and was caught.
14Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇            string line = String.Format("An exception of type {0} occurred and was caught."base.Exception.GetType().FullName);
15Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇            this.Writer.WriteLine(line);
16Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        }

17Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇
18Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        protected override void WriteExceptionType(Type exceptionType) 
19Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        {
20Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇            base.Indent();
21Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇            base.Writer.WriteLine("Type : {0}", exceptionType.FullName);
22Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        }

23Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇
24Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        public override void Format() 
25Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        {
26Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇            //this.Writer.WriteLine("Message : {0}", message);
27Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇            this.WriteDescription();
28Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇            //this.WriteExceptionType(base.Exception.GetType());
29Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇            base.WriteMessage(base.Exception.Message);
30Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        }

31Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇
32Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    }

四.创建自定义的异常处理器

异常处理应用程序块允许您包装并使用您自己的例外业务处理流程,例如在时间记录系统中填写一个事件,利用业务规范进行包装和替代,利用另外的记录系统进行记录(比较常用的有Log4net,前段时间深渊野鱼介绍的,还没用过^_^),这种灵活的可配置性,将允许您在不同的异常类型及其策略中灵活的配置。

可以通过实现ExceptionHandler抽象类,来创建定制的Handler

1 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇public   abstract   class  ExceptionHandler : ConfigurationProvider, IExceptionHandler

该抽象类继承ConfigurationProvider类,并实现IExceptionHandler接口。ConfigurationProvider抽象类实现了IConfigurationProvider接口,用来读取配置数据。

1 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇public   abstract   class  ConfigurationProvider : IConfigurationProvider

使用支持序列化的数据类型作为配置参数,还有要注意数据类型的简单,避免“Exception Handling Exceptions

看一下在Enterprise Library Quick Start中提供了定制Handler的实现:

 1 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇 /// <summary>
 2Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇  /// Summary description for GlobalPolicyExceptionHandler.
 3Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇  /// </summary>

 4 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇   public   class  AppMessageExceptionHandler : ExceptionHandler
 5 Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇   {
 6Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    public AppMessageExceptionHandler()
 7Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    {
 8Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    }

 9Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇
10Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    public override void Initialize(ConfigurationView configurationView)
11Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    {
12Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    }

13Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇
14Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    public override Exception HandleException(Exception exception, string policyName, Guid correlationID) 
15Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    {
16Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇      DialogResult result = this.ShowThreadExceptionDialog(exception);
17Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇
18Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇      // Exits the program when the user clicks Abort.
19Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇      if (result == DialogResult.Abort) 
20Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇        Application.Exit();
21Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇
22Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇      return exception;
23Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    }

24Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇
25Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    // Creates the error message and displays it.
26Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    private DialogResult ShowThreadExceptionDialog(Exception e) 
27Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    {
28Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇      string errorMsg = e.Message + Environment.NewLine + Environment.NewLine;
29Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇
30Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇      return MessageBox.Show(errorMsg, "Application Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
31Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇    }

32Enterprise Library Step By Step系列(十二):异常处理应用程序块——进阶篇  }

结束语:异常处理应用程序块的进阶篇就写到这里了。