请问三层架构开发思想:数据层的异常在哪个层捕获?用抛出异常来表示返回信息好么?

lufree 2005-12-02 12:18:46
现在假设有一个三层架构的程序,数据访问层DA,逻辑层BL,表示层WEB。


1.假如在操作数据库时DA层遇到一个异常,比如说“sqlserver不存在或者访问被拒绝”的这种异常,是应该在哪个层中捕获呢?是在数据层直接捕获?还是数据层不捕获而在逻辑层捕获?还是这两个层都不捕获最后由表示层来捕获呢?是在每个层都要捕获还是底层捕获然后上层靠方法的返回值来确定方法是否成功?


2.还是在这个程序中,举例说用户注册,当BL调用DA的一个方法把一个用户的信息插入用户表时,在插入之前会检测这个用户的登录名是否在数据库中已经存在,假如这个登录名已经存在,那么采用以下哪种方法更好?

a.表示层(逻辑层)根据所调用的逻辑层(数据层)方法的返回值来提示用户注册是否成功,即定义返回true为插入成功返回false为不成功。

b.还是在逻辑层采用抛出一个异常的方式(throw new SqlException("当前登录名已经存在!")),然后在表示层try一下,捕获错误时直接把错误信息lbMessage.Text = ex.Message;呢?


这几种解决方法都是我现在琢磨的,当然各位如果有更好的方法也欢迎不吝赐教,由于刚刚接触三层开发,不太熟悉,所以问题较多,而且写得也比较多,可能各位看着比较费劲吧。我看PetShop中那个SQLHelper层没有捕获异常而是在上层去捕获的....

请各位指教,谢谢了。
...全文
7923 153 打赏 收藏 转发到动态 举报
写回复
用AI写文章
153 条回复
切换为时间正序
请发表友善的回复…
发表回复
Jianyi 2006-04-26
  • 打赏
  • 举报
回复
也说一下自己的意见:

系统异常或业务逻辑行的异常不要直接在代码中处理,除非内要捕获某个异常然后做其他的处理.

统一的在页面基类的On_Err方法或在Globals的Applicaton_Err中处理,对异常信息格式化一下,以一种更友好的方式显示给终端用户,并且若有必要,将错误信息记录到日值.

方法的优点:减少了代码中大量的try catch
zhouheng123456 2006-04-26
  • 打赏
  • 举报
回复
个人认为..异常机制要看你的系统了类型了..

如果是面向大众的一个门户型,具有不固定的使用群体.
那么建议自定一个返回值的机制,因为在这些业务或是操作上的错误是很常见的..
而异常的catch和throw都有一定的系统开销..不利于性能方面..

但如果是一个有固定的使用人群,就以思归说的比较好...
在底层写入异常的log,然后抛出log的ID存入到一个日志管理,或是真接给出错页
如果是业务异常大可不必..业务异常可以自定义.然后在表现层获得,
自定义异常里应该有一个msg或msgid的成员...表现层在获得异常的时候根据他来报出错误信息.
注意,在应用程序当中,最好不要去catch系统自定义异常,至少开发过程中不要,这样可以避免产生一些难以发现的bug(项目经验)
bufan2162 2006-04-26
  • 打赏
  • 举报
回复
讨论真热烈啊,我要好好努力了
WardenMoon 2006-04-26
  • 打赏
  • 举报
回复
学习
claus2001 2006-04-03
  • 打赏
  • 举报
回复
学习
wxm4585 2006-04-03
  • 打赏
  • 举报
回复
留个名,学习,UP
kofkyo 2006-01-27
  • 打赏
  • 举报
回复
Mark
maple_leafs 2006-01-27
  • 打赏
  • 举报
回复
up
lucidcai 2006-01-27
  • 打赏
  • 举报
回复
学习
qwerttyy 2006-01-27
  • 打赏
  • 举报
回复
学习
ywuwgij 2006-01-27
  • 打赏
  • 举报
回复
我一般都是在继承一个基类,在基类中有一个公共一异常对象
longhorn008 2006-01-27
  • 打赏
  • 举报
回复
mark
kill3434 2006-01-27
  • 打赏
  • 举报
回复
mark
yjdabc 2006-01-18
  • 打赏
  • 举报
回复
up
alonepb 2006-01-18
  • 打赏
  • 举报
回复
继续,希望最后谁来最终总结出最优方式
wfqn 2006-01-12
  • 打赏
  • 举报
回复
再贴一段我的代码,这是具体应用中的代码,使用了大量的try catch,但我可以保证异常发生的几率非常低,甚至几个月也不会发生一次。逻辑性错误或者使用者输入错误都通过判断属性值得方式实现。

private void Start()
{
//初始化
int time_limit;
TEseries.Core.Configure objConfigure = null;
TEseries.Core.Database.Connect conn;

//系统配置对象
try
{
objConfigure = TEseries.Core.Configure.getInstance("TEseries.Cms");
}
catch(Exception err)
{
throw new TEseries.Core.TException(err.Message, err);
}

//这是一个逻辑性错误
if (objConfigure.ID == 0)
{
//向客户端提供错误信息
Console.WriteLine("系统配置不存在!");

//关闭数据库
try { TEseries.Core.Api.CloseConnection(conn); }
catch {}

//退出程序运行
return;
}

//开始发布
while(true)
{
//连接数据库
try { conn = TEseries.Core.Api.Connection("TEseries.Cms"); }
catch (TEseries.Core.TException err) { throw new TEseries.Core.TException(err.Message, err); }

//频道发布者
try
{
this.ChannelPublisher();
}
catch(Exception err)
{
//抛出异常
throw new TEseries.Core.TException(err.Message, err);
}

//页面发布者
try
{
this.PagePublisher();
}
catch(Exception err)
{
//抛出异常
throw new TEseries.Core.TException(err.Message, err);
}

//关闭数据库
try { TEseries.Core.Api.CloseConnection(conn); }
catch {}

//休息
time_limit = TEseries.Core.Number.GetInt(objConfigure.GetValue("PublisherTimeLimit"));
time_limit = time_limit > 3 ? time_limit : 3;
Thread.Sleep(time_limit * 1000);
}
}
wfqn 2006-01-12
  • 打赏
  • 举报
回复
to: wwwsq(wwwsq) 我测试了,你说得没错!

所以要看需求,如果需要频繁抛出异常,那我的方法就很不合适,可以用返回值代替。如果异常出现的频率很低,比如说只是检测数据库异常,那么就值得付出这个代价了。

还是来个总结吧,如果是系统级错误(比如数据库异常、或者网络异常)才用try catch来捕获,如果是逻辑错误或者使用者输入错误,那就用返回值的方式判断,try catch不能在出错率较高的代码中使用。我想这应该是基本原则吧。
OSCAR_NJU 2006-01-12
  • 打赏
  • 举报
回复
关注
abc1223 2006-01-05
  • 打赏
  • 举报
回复
CnEve 2006-01-05
  • 打赏
  • 举报
回复
我通常将类库里的异常抛出,在表示层如出现异常则进行捕获
类库中的方法:
try{....}catch{throw;} //若有异常直接抛出。

表示层:
try{
//调用一系列方法...
}
catch(Exception ex)
{
//统一捕获
}
加载更多回复(131)

62,074

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧