异常处理模块是大型系统必备的一个组件,精心设计的异常处理模块可提高系统的健壮性。下面从我理解的角度,谈谈异常处理的方方面面。我的设计仅仅限定于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;}}
 

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

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异常处理的核心部分在本篇的第三部分,设置捕获系统抛出的异常。

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

  1. 解析大型.NET ERP系统 设计通用Microsoft Excel导入功能

    做企业管理软件很难避免与Microsoft Excel打交道,常常是软件做好了,客户要求说再做一个Excel导入功能.导入Excel数据的功能的难度不大,从Excel列数据栏位的取值,验证值,再导入到 ...

  2. 解析大型.NET ERP系统:十三种界面设计模式

    成熟的ERP系统的界面应该都是从模板中拷贝出来的,各类功能的界面有规律可遵循.软件界面设计模式化或是艺术性的创作,我认可前者,模式化的界面客户容易举一反三,降低学习门槛.除了一些小部分的功能界面设计特 ...

  3. 解析大型.NET ERP系统架构设计 Framework+ Application 设计模式

    我对大型系统的理解,从数量上面来讲,源代码超过百万行以上,系统有超过300个以上的功能,从质量上来讲系统应该具备良好的可扩展性和可维护性,系统中的功能紧密关联.除去业务上的复杂性,如何设计这样的一个协 ...

  4. 解析大型.NET ERP系统 20条数据库设计规范

    数据库设计规范是个技术含量相对低的话题,只需要对标准和规范的坚持即可做到.当系统越来越庞大,严格控制数据库的设计人员,并且有一份规范书供执行参考.在程序框架中,也有一份强制性的约定,当不遵守规范时报错 ...

  5. 解析大型.NET ERP系统 高质量.NET代码设计模式

    1 缓存 Cache 系统中大量的用到缓存设计模式,对系统登入之后不变的数据进行缓存,不从数据库中直接读取.耗费一些内存,相比从SQL Server中再次读取数据要划算得多.缓存的基本设计模式参考下面 ...

  6. 解析大型.NET ERP系统 多国语言实现

    实现多国语言有许多种实现方案,无外乎是一种字符串替换技术,将界面控件的文本标签替换成相应语言的文字..NET Windows Forms实现多国语言的方法有以下几种: 1 .NET的方案,使用资源文件 ...

  7. 你不知道的服装ERP系统的功能模块与好处!

    现如今随着企业信息化管理的不断发展,越来越多的企业通过使用管理软件提高了工作能力,提高了投入产出比.随着电子商务的不断发展,现在越来越多的服装卖家需要处理大量的数据,而使用ERP系统可以简化工作流程. ...

  8. ERP系统标准功能模块

    税务管理模块 1.税务管理的重要性 现代企业的税务筹划有利于最大限度实现财务目标,在不违反政策.法规的前提下对企业筹资.投资.经营等方面活动,乃至生产经营.利润分配等环节的业务进行事先策划,制定一整套 ...

  9. 电商ERP系统的功能模块及好处

    ERP系统在提高企业工作效率方面起着至关重要的作用,可以帮助企业简化工作流程,实现数据自动化处理.那么ERP系统能够给电商企业带来哪些实质性的好处呢?下面一起来了解一下相关的知识吧! 电商ERP是什么 ...

最新文章

  1. ABP入门系列(7)——分页实现
  2. Unity(1)控制反转
  3. Func vs. Action vs. Predicate [复制]
  4. 皮一皮:经历过的举手报道...
  5. 网络编程学习笔记(使用select函数的TCP和UDP回射服务器程序)
  6. Django框架环境搭建遇到的问题
  7. mysql gbk支持_mysql如何支持gbk编码
  8. Thymeleaf模板如何获取springMVC返回的model值
  9. 因限制游戏驿站等WSB概念股交易 Robinhood遭散户集体诉讼
  10. 神经网络画图-ConvNetDraw(简单实用)
  11. 【考试总结贴】工程测量学
  12. vue中手机号码+座机号码、邮箱正则校验规则封装
  13. 有人设备在工业物联网解决方案中的应用
  14. Ubuntu状态栏显示网速,内存利用率等信息——sysmonitor
  15. 【腾讯敏捷转型No.7】QQ邮箱如何通过敏捷成为行业第一
  16. CSAPP-Lab02 Bomb Lab 详细解析
  17. java播放器_Java视频播放器的制作
  18. android炫酷的动画效果
  19. 微信中直接下载APK
  20. [企业管理]宽容与尊严

热门文章

  1. Web 开发与设计之 Google 兵器谱
  2. 好多Javascript日期选择器呀-5
  3. 泛型推断类型不符合上限
  4. 堆状态分析的利器——gperftools的Heap Profiler
  5. 一种不会导致资源泄露的“终止”线程的方法
  6. CUDA Samples: green ball
  7. 解决Windows7下vs2008 Active control test container 不能运行的问题
  8. 【Qt】Qt5在ubuntu16.04无法输入中文解决方式
  9. 在C语言中break语句称为,在C语言中,break语句的功能是退出函数
  10. Java解决递归栈溢出_方法递归调用中java栈溢出的问题 及 解答 | 学步园