C# 我应该在WebApi应用程序的较低层上使用try/catch语句吗?

C# 我应该在WebApi应用程序的较低层上使用try/catch语句吗?,c#,.net,asp.net-web-api,exception-handling,C#,.net,Asp.net Web Api,Exception Handling,我有一个简单的WebApi应用程序,它代表一个用户存储。我有DAL和BLL层。我使用ExceptionFilters处理异常 public class HandleExceptionsAttribute : ExceptionFilterAttribute { private readonly ILogger logger; public HandleExceptionsAttribute(ILogger logger) {

我有一个简单的WebApi应用程序,它代表一个用户存储。我有DAL和BLL层。我使用
ExceptionFilters
处理异常

public class HandleExceptionsAttribute : ExceptionFilterAttribute
    {
        private readonly ILogger logger;

        public HandleExceptionsAttribute(ILogger logger)
        {
            this.logger = logger;
        }

        public override void OnException(HttpActionExecutedContext context)
        {
            logger.LogError(context.Exception);
        }
    }
它将我的异常写入日志文件。我应该在较低的层(DAL、BLL)上使用try/catch语句吗?我得到一个建议,尽量减少“try-catch”条款。我想我需要在异常不出现在控制器层的时候排除它们。我假设这意味着我应该在DAL层中使用try/catch语句。我应该为BLL层设置异常,为控制器层设置异常。看起来是这样的:

DAL层

public class UserRepository
    {
        public IEnumerable<User> GetAll()
        {
            IEnumerable<User> users; 

            try
            {
                users = context.GetUsers();
            }
            catch(SomeSpecificException specExc)
            {
                throw specExc;
            }
            catch(Exception exc)
            {
                throw exc;
            }
        }
    }
public class UserService
    {
        public IEnumerable<User> GetAllUsers()
        {
            IEnumerable<Users> users;

            try
            {
                users = userRepository.GetAll();
            }
            catch(PreviousSpecificException specExc)
            {
                throw specExc;
            }
            catch(OneMoreSpecificException sExc)
            {
                throw sExc;
            }
            catch(Exception exc)
            {
                throw exc;
            }
        }
    }
公共类用户存储库
{
公共IEnumerable GetAll()
{
i无数用户;
尝试
{
users=context.GetUsers();
}
捕获(SomeSpecificException规范)
{
抛出specExc;
}
捕获(异常exc)
{
抛出exc;
}
}
}
BLL层

public class UserRepository
    {
        public IEnumerable<User> GetAll()
        {
            IEnumerable<User> users; 

            try
            {
                users = context.GetUsers();
            }
            catch(SomeSpecificException specExc)
            {
                throw specExc;
            }
            catch(Exception exc)
            {
                throw exc;
            }
        }
    }
public class UserService
    {
        public IEnumerable<User> GetAllUsers()
        {
            IEnumerable<Users> users;

            try
            {
                users = userRepository.GetAll();
            }
            catch(PreviousSpecificException specExc)
            {
                throw specExc;
            }
            catch(OneMoreSpecificException sExc)
            {
                throw sExc;
            }
            catch(Exception exc)
            {
                throw exc;
            }
        }
    }
公共类用户服务
{
公共IEnumerable GetAllUsers()
{
i无数用户;
尝试
{
users=userRepository.GetAll();
}
捕获(以前的特殊异常规范)
{
抛出specExc;
}
捕获(OneMoreSpecificException sExc)
{
扔性;
}
捕获(异常exc)
{
抛出exc;
}
}
}

看起来不太好。我是否可以拒绝使用我所有的try/catch语句,并对所有工作进行例外筛选?

您应该通过以下问题应用try/catch块

  • 是否要在特定层“处理”异常?这意味着, 您是否希望在以下情况下提供任何替代方案或日志记录等 发生异常
  • 你是唯一一个要消耗这层的人吗?如果其他人可以使用您的BAL或DAL,他将如何知道您的BAL或DAL中是否发生任何异常

  • 如果您不想在异常发生时在BAL/DAL中执行任何操作,则不应该在那里使用try catch块。如果您希望外层应该处理异常,“异常”应该出现在外层,外层应该有try/catch。

    我认为这主要是基于观点的,但您应该只在设计需要时处理异常。日志记录是开发人员的需要

    我在你的一条评论中看到,你想发出“漂亮的错误信息”。这完全是一种设计需要,但是对于程序的UI层,因此不应该处理BLL中的异常。(好吧,真正的设计需要是你不希望你的程序在抛出的第一个异常上崩溃,但你明白了)

    在同一主题上,我建议在尽可能高的层上实现日志,这样您也可以记录格式良好的消息


    当然,如果有必要,您总是可以尝试/捕获BLL,但是重新显示一个新异常,将原始异常作为其内部异常

    在我的例子中,我想处理这个异常,并返回对purpose的响应,以便在UI上处理它,并生成相当的错误消息。如果您不想在DAL或BAL层上执行任何操作(例如重试或日志记录等),您可以跳过DAL/BAL中的try/catch块。在控制器中处理异常并相应地处理响应。捕获并释放异常处理(捕获异常只是为了重新抛出它们)是个坏主意。充其量,catch条款也无济于事。在最坏的情况下,当你写
    throw-ex而不仅仅是
    抛出可能会破坏有用的堆栈跟踪信息。