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


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

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

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

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

创建数据库:

 

 

 

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%)

创建表:

 

CREATE   TABLE   [ dbo ] . [ Log ]  (
    
[ LogID ]   [ int ]   IDENTITY  ( 1 1 NOT   NULL  ,
    
[ EventID ]   [ int ]   NULL  ,
    
[ Category ]   [ nvarchar ]  ( 64 ) COLLATE SQL_Latin1_General_CP1_CI_AS  NOT   NULL  ,
    
[ Priority ]   [ int ]   NOT   NULL  ,
    
[ Severity ]   [ nvarchar ]  ( 32 ) COLLATE SQL_Latin1_General_CP1_CI_AS  NOT   NULL  ,
    
[ Title ]   [ nvarchar ]  ( 256 ) COLLATE SQL_Latin1_General_CP1_CI_AS  NOT   NULL  ,
    
[ Timestamp ]   [ datetime ]   NOT   NULL  ,
    
[ MachineName ]   [ nvarchar ]  ( 32 ) COLLATE SQL_Latin1_General_CP1_CI_AS  NOT   NULL  ,
    
[ AppDomainName ]   [ nvarchar ]  ( 2048 ) COLLATE SQL_Latin1_General_CP1_CI_AS  NOT   NULL  ,
    
[ ProcessID ]   [ nvarchar ]  ( 256 ) COLLATE SQL_Latin1_General_CP1_CI_AS  NOT   NULL  ,
    
[ ProcessName ]   [ nvarchar ]  ( 2048 ) COLLATE SQL_Latin1_General_CP1_CI_AS  NOT   NULL  ,
    
[ ThreadName ]   [ nvarchar ]  ( 2048 ) COLLATE SQL_Latin1_General_CP1_CI_AS  NULL  ,
    
[ Win32ThreadId ]   [ nvarchar ]  ( 128 ) COLLATE SQL_Latin1_General_CP1_CI_AS  NULL  ,
    
[ Message ]   [ nvarchar ]  ( 2048 ) COLLATE SQL_Latin1_General_CP1_CI_AS  NULL  ,
    
[ FormattedMessage ]   [ ntext ]  COLLATE SQL_Latin1_General_CP1_CI_AS  NULL  
ON   [ PRIMARY ]  TEXTIMAGE_ON  [ PRIMARY ]
GO

 

创建存储过程:

 

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

 

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

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

 

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

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

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

 

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

 

 1 /**/ /// <summary>
 2        /// 日志策略
 3        /// </summary>
 4        /// <param name="sender"></param>
 5        /// <param name="e"></param>

 6          private   void  btn_Log_Click( object  sender, System.EventArgs e)
 7          {
 8            try
 9            {
10                Exception ex = new Exception();
11                throw ex;
12            }

13            catch(Exception ex)
14            {
15                bool Flag = ExceptionPolicy.HandleException(ex,"Log Policy");
16
17                if(Flag)
18                {
19                    throw;
20                }

21            }

22        }

补充一点:在项目中要添加对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 /**/ /// <summary>
 2    /// Summary description for AppTextExceptionFormatter.
 3    /// </summary>    

 4      public   class  AppTextExceptionFormatter : TextExceptionFormatter
 5      {
 6        public AppTextExceptionFormatter(TextWriter writer, Exception exception)
 7            : base (writer, exception) 
 8            {
 9            }

10        
11        protected override void WriteDescription() 
12        {
13            // An exception of type {0} occurred and was caught.
14            string line = String.Format("An exception of type {0} occurred and was caught."base.Exception.GetType().FullName);
15            this.Writer.WriteLine(line);
16        }

17
18        protected override void WriteExceptionType(Type exceptionType) 
19        {
20            base.Indent();
21            base.Writer.WriteLine("Type : {0}", exceptionType.FullName);
22        }

23
24        public override void Format() 
25        {
26            //this.Writer.WriteLine("Message : {0}", message);
27            this.WriteDescription();
28            //this.WriteExceptionType(base.Exception.GetType());
29            base.WriteMessage(base.Exception.Message);
30        }

31
32    }

 

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

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

 

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

1 public   abstract   class  ExceptionHandler : ConfigurationProvider, IExceptionHandler

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

1 public   abstract   class  ConfigurationProvider : IConfigurationProvider

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

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

 

 1 /**/ /// <summary>
 2  /// Summary description for GlobalPolicyExceptionHandler.
 3  /// </summary>

 4    public   class  AppMessageExceptionHandler : ExceptionHandler
 5    {
 6    public AppMessageExceptionHandler()
 7    {
 8    }

 9
10    public override void Initialize(ConfigurationView configurationView)
11    {
12    }

13
14    public override Exception HandleException(Exception exception, string policyName, Guid correlationID) 
15    {
16      DialogResult result = this.ShowThreadExceptionDialog(exception);
17
18      // Exits the program when the user clicks Abort.
19      if (result == DialogResult.Abort) 
20        Application.Exit();
21
22      return exception;
23    }

24
25    // Creates the error message and displays it.
26    private DialogResult ShowThreadExceptionDialog(Exception e) 
27    {
28      string errorMsg = e.Message + Environment.NewLine + Environment.NewLine;
29
30      return MessageBox.Show(errorMsg, "Application Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
31    }

32  }

转载于:https://www.cnblogs.com/xiaotao823/archive/2008/01/18/1044742.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值