解析大型.NET ERP系统 设计异常处理模块

news/2024/7/1 2:40:42

异常处理模块是大型系统必备的一个组件,精心设计的异常处理模块可提高系统的健壮性。下面从我理解的角度,谈谈异常处理的方方面面。我的设计仅仅限定于Windows Forms,供参考。

1 定义异常类型

.NET 框架定义很多异常类型,ERP系统中根据实际的需要,我们再增加一些自定义的异常类型。

数据库访问异常:LLBL Gen Pro已经定义几种常见的异常类型,常见的异常类型及其作用简介。

ORMConcurrencyException     并发异常,更新实体时实体已经被删除,删除时有约束无法删除
ORMEntityOutOfSyncException. (Adapter) 实体保存之后没有重新读取,使用它的属性时抛出ORMEntityIsDeletedException   实体已经删除,但仍然访问它的属性
ORMFieldIsNullException.  在实体的属性值设为NULL之后,仍然去访问它的属性性
ORMEntityValidationException  自定义异常
ORMFieldIsReadonlyException  给只读的属性赋值
ORMInheritanceInfoException 查询执行过程中检测到错误
ORMQueryConstructionException ORM框架构造动态查询(Dynamic Query Engine )失败时ORMQueryExecutionException  ORM框架执行动态查询(Dynamic Query Engine )失败时
ORMRelationException  关系设定错误
ORMSecurityException 用于授权(Authorization)失败后
ORMValueTypeMismatchException 属性的值与类型不匹配

业务逻辑异常: 定义应用程序中的业务逻辑异常类型

AccessDeniedException 模块或功能当前登入用户无权限访问
CrystalReportException 水晶报表的运行库加载失败,报表连接数据库失败,报表公式解析失败等异常
EntityValidationException  业务对象验证失败
FieldValidationException  业务对象的属性验证失败
LicenseException  许可证授权异常
FtpException: 文件服务器连接失败或授权失败等异常

2 封装异常信息

在系统抛出异常时,我们需要知道抛出异常的程序的完整信息,比如程序版本,最后更新时间,发生异常的堆栈等,有了这些信息,技术支持或程序员可以快速定位异常,分析可能的原因。

为此目的,定义一个异常信息封装类,包含传入异常,封装更丰富的异常信息。

public sealed class ExceptionDetail
{private System.Exception _exception;private void Initialize(){if (this._exception != null){builder = builder.Append(format).Replace("\n", "\r\n");builder.Append(string.Format("Date: {0} {1}\r\n", DateTime.Today.ToShortDateString(), DateTime.Now.ToLongTimeString()));builder.Append(string.Format("Version: {0} ({1})\r\n", AssemblyVersion.Version, File.GetLastWriteTime(typeof(AssemblyVersion).Assembly.Location)));builder.Append(string.Format("Source: {0}\r\n", innerException.Source));builder.Append(string.Format("Class: {0}\r\n", (innerException.TargetSite != null) ? innerException.TargetSite.DeclaringType.ToString() : null));builder.Append(string.Format("Member Type: {0}\r\n", (innerException.TargetSite != null) ? innerException.TargetSite.MemberType.ToString() : null));builder.Append(string.Format("Member Name: {0}\r\n", innerException.TargetSite));builder.Append(string.Format("Exception Type: {0}\r\n", innerException.GetType().FullName));builder.Append(string.Format("Data: {0}\r\n", obj2));builder.Append("\r\n");builder.Append(string.Format("Exception: {0}", message));}}
}

 

3  捕获系统抛出的异常

对Windows Forms程序,可以通过两个属性设定完成对系统异常的捕获。

CustomExceptionHandler eh = new CustomExceptionHandler();
Application.ThreadException += new ThreadExceptionEventHandler(eh.OnThreadException);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

CustomExceptionHandler 是一个处理异常信息密封类,源代码如下,目的是为了统一系统的异常错误提示界面。

internal sealed class CustomExceptionHandler
{public bool IsDebug = false;public CustomExceptionHandler(){}//Handle the exception  eventpublic void OnThreadException(object sender, ThreadExceptionEventArgs t){if (IsDebug) 
Debug.Assert(false, t.Exception.Message, t.Exception.StackTrace); DialogResult result = DialogResult.Cancel;try{result = this.ShowThreadExceptionDialog(t.Exception);}catch{try{result = MessageBox.Show(string.Format("{0}\r\n\r\n{1}", t.Exception.Message, t.Exception.StackTrace), "Fatal Error", MessageBoxButtons.OK, MessageBoxIcon.Error);}finally{Application.Exit();}}if (result == DialogResult.Abort) Application.Exit();}private DialogResult ShowThreadExceptionDialog(Exception e){return DialogResult.Cancel;}}
 

异常显示对话框显示异常,参考下面的界面。

image

 

4  程序中可通过throw语句抛出异常,实现N层回滚

保存新实体对象时,判断数据是否重复:

if (salesContract.IsNew)
{ISalesContractManager salesContractManager = CreateProxyInstance<ISalesContractManager>();if (salesContractManager.IsSalesContractExist(salesContract.ContractNo))throw new RecordDuplicatedException(salesContract.ContractNo, "Cotract No. is already used");
}

发生属性改变事件时,触发验证:

public override bool ValidateFieldValue(IEntityCore involvedEntity, int fieldIndex, object value)
{bool result = base.ValidateFieldValue(involvedEntity, fieldIndex, value);if (!result) return false;switch ((SalesContractFieldIndex) fieldIndex){case SalesContractFieldIndex.CustomerNo:return this.ValidateCustomerNo((string) value);}return true;
}private bool ValidateCustomerNo(string value)
{if (!string.IsNullOrEmpty(value)){ICustomerManager customerManager = ClientProxyFactory.CreateProxyInstance<ICustomerManager>();customerManager.ValidateCustomerNo(Shared.CurrentUserSessionId, value);}return true;
}
 

Windows Forms异常处理的核心部分在本篇的第三部分,设置捕获系统抛出的异常。


http://lihuaxi.xjx100.cn/news/244592.html

相关文章

在IIS中为SQL Server 2008配置报表服务

不知道是不是SQL Server 2008的Bug&#xff0c;我在安装了SQL2008后&#xff08;选择了安装报表服务的&#xff09;&#xff0c;但是在IIS中根本没有报表服务的虚拟目录。只是这么一个问题&#xff0c;其他BI设计器、报表服务等都还算正常。 要正常使用报表服务则需要手动添加报…

PHP面试常考内容之Memcache和Redis(2)

你好&#xff0c;是我琉忆。继周一&#xff08;2019.2-18&#xff09;发布的“PHP面试常考内容之Memcache和Redis&#xff08;1&#xff09;”后&#xff0c;这是第二篇&#xff0c;感谢你的支持和阅读。本周&#xff08;2019.2-18至2-22&#xff09;的文章内容点为以下几点&am…

(原创)Python文件与文件系统系列(5)——stat模块

stat模块中定义了许多的常量和函数&#xff0c;可以帮助解释 os.stat()、os.fstat()、os.lstat()等函数返回的 st_result 类型的对象。 通常使用 os.path.is*() 这类函数来测试一个文件的类型&#xff0c;这些方法对同一个文件进行多次测试时&#xff0c;stat()系统调用都是不可…

maven项目中,如何导出项目所有的jar

1.找到pom.xml&#xff0c;右键 选择Run As >> Maven build… 在上图的Goals框中输入“dependency:copy-dependencies”&#xff0c;后点击“Run”即可。 当控制台出现“BUILD SUCCESS”时&#xff0c;表示build成功。 在当前项目的根目录“targed/dependency”下可查…

转 The connection to adb is down, and a severe error

相信不少同学和我一样遇到这个问题&#xff0c;有时候搞的还要重启电脑&#xff0c;那究竟是什么原因导致的呢&#xff0c;很明显&#xff0c;你的端口被占用了&#xff0c;那下面给出终极解决方案&#xff1a; 一、首先描述症状&#xff0c;如下图 二、出现问题了&#xff0c;…

想要确保架构目标达成?适合度函数了解一下

Paula Paul和Rosemary Wang撰写的一篇博文中介绍了适应度函数&#xff08;fitness function&#xff09;的基本概念、入门方法&#xff0c;并给出了如何验证各种架构质量的一些实例。文中提出&#xff0c;适应度函数驱动开发的方法可用于编写测定系统符合架构目标的测试&#x…

浅谈HTTP中Get与Post的区别

Http定义了与服务器交互的不同方法&#xff0c;最基本的方法有4种&#xff0c;分别是GET&#xff0c;POST&#xff0c;PUT&#xff0c;DELETE。URL全称是资源描述符&#xff0c;我们可以这样认为&#xff1a;一个URL地址&#xff0c;它用于描述一个网络上的资源&#xff0c;而H…

mysql字段定义成text类型的严重影响查询性能

1.使用text字段查询的结果&#xff1a; 2.去掉这个字段后的查询 两者大概相差了0.9秒&#xff0c;严重影响了性能