在您离开谷歌之前,我已经阅读了很多关于异常处理的文章,帖子和评论,但我仍然坚持这些具体要点。
鉴于以下示例,您将如何处理以下情况?
如果我在DAL层中记录它,它将在全局处理程序中再次记录(使用elmah)。我可以让它传播,但是如果ServiceLayer需要将该异常转换为用户更友好的消息或者可能用于事务目的(想想回滚)会发生什么?我将丢失在DAL异常中收集的信息(无论如何消息,不一定是堆栈跟踪)。
// UI
public static GetUser(int userId)
{
// Should I do validation here or in service layer
try
{
IUserService s = new UserService(userId);
s.GetUser(userId);
}
catch(ServiceLayerException ex)
{
// ex.Message displayed to user
}
}
// Service layer
public User GetUser(int userId)
{
try
{
return repo.GetUser(userId);
}
catch(DALException ex)
{
// user-friendly message displayed to user
throw new ServiceLayerException("User does not exist");
}
}
// DAL
public User GetUser(int userId)
{
try
{
// Query for user, if fails throw DALException
return userId;
}
catch (SqlException ex)
{
throw new DALException("Could not retrieve user with userId " + userId.ToString());
}
}
答案 0 :(得分:1)
我个人更喜欢登录煤层 - 实际发生异常的地方,所以在第一种情况下我会登录DAL。如果我们不想传播错误,或者允许elmah记录错误,Bal(服务层)可以处理错误(这不是坏事,因为它将显示在错误页面上并帮助跟踪异常)。 服务层还可以将DAL错误作为内部异常传递,以便在需要时可以在访问期间/之后访问它 - 并且异常iteslf可以根据需要在层之间进行变更。用户通常不会想要这样的信息,只是收到通常的愚蠢消息。 也可以使用事件来收集异常数据(使用专门的事件争论)并且只返回布尔方法返回,这可以更加可控和可定制 - 尽管这会使你有责任传播或者不传播,这很可能仅用于“预期”例外。