程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> Enterprise Library Step By Step系列(十二)異常處理應用程序塊 - 進階篇

Enterprise Library Step By Step系列(十二)異常處理應用程序塊 - 進階篇

編輯:關於.NET

一.把異常信息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

創建存儲過程:

1CREATE 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)
18AS
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)
51GO

該SQL語句默認的路徑為C:\Program Files\Microsoft Enterprise Library\src\Logging\Sinks\Database\Scripts,直接運行CreateLoggingDatabase.cmd即可。

2.運行配置工具,我們創建一個日志和監測應用程序塊,並建一個Database Sink,具體的配置方法在日志和監測應用程序塊中講過了,這裡就不重復了,我們看一下它的配置:

注意設置StoredProcName為WriteLog,就是我們剛才創建的存儲過程。

3.同時再創建一個Category,起名為DataException,並設置它的Sink為Database Sink。4.設置Logging Handler的LogCategory為我們剛才創建的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

1public abstract class ExceptionHandler : ConfigurationProvider, IExceptionHandler

該抽象類繼承ConfigurationProvider類,並實現IExceptionHandler接口。ConfigurationProvider抽象類實現了IConfigurationProvider接口,用來讀取配置數據。

1public 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 }

結束語:異常處理應用程序塊的進階篇就寫到這裡了。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved