【问题标题】:Is this an efficient way to catch and handle exceptions / errors?这是捕获和处理异常/错误的有效方法吗?
【发布时间】:2011-12-24 03:12:35
【问题描述】:

我现在使用以下代码在我的服务层中捕获错误并引发异常:

 ...
            if (pk == null || rk == null) return null;
            try
            {
                var item = repo.GetPkRk(pk, rk);
                return (T)item;
            }
            catch (Exception ex)
            {
                throw new ServiceException("", typeof(T).Name + rk + " data retrieval error");
            }
  ...

ServiceException 类:

public class ServiceException : ApplicationException {     
        public Dictionary<string, string> Errors { get; set; }
        public ServiceException() : this(null) {}enter code here
        public ServiceException(string key, string message)
        {
            Errors = new Dictionary<string, string>(); 
            Errors.Add(key, message);
        }
        public ServiceException(Exception ex)
            : base("Service Exception", ex)
        {
            Errors = new Dictionary<string, string>();
        }
    }

然后在我的控制器中捕获错误消息:

catch (Exception e) { log(e); }

终于在log方法中处理了:

protected void log(Exception ex)
        {
            if (ex is ServiceException)
            {
                ModelState.Merge(((ServiceException)ex).Errors);  
            } else {
                Trace.Write(ex);
                ModelState.AddModelError("", "Database access error: " + ex.Message);
            }
        }

任何人都可以评论这是一个好还是坏的方法。我之前有过关于捕获内部异常的评论。这可能吗?如果可以,那么我如何才能捕获并保留内部异常详细信息。

更新 1

我修改了异常类,所以有一个使用 ex 的构造函数。不确定这是否理想,但我认为它有效。任何关于如何改进的建议将不胜感激。

更新 2

下面的代码失败并显示一条消息

Error   2   Property or indexer 'System.Exception.InnerException' cannot be assigned to -- it is read only

我不知道如何解决这个问题。

public class ServiceException : ApplicationException {

    public Dictionary<string, string> Errors { get; set; }
    public ServiceException() : this(null) {}
    public ServiceException(Exception ex, string key, string message)
    {
        Errors = new Dictionary<string, string>();
        InnerException = ex;
        Errors.Add(key, message);
    }
    public ServiceException(string key, string message)
    {
        Errors = new Dictionary<string, string>(); 
        Errors.Add(key, message);
    }
    public ServiceException(Exception ex)
        : base("Service Exception", ex)
    {
        Errors = new Dictionary<string, string>();
    }
}

【问题讨论】:

标签: c# exception exception-handling


【解决方案1】:

在几乎所有情况下,您根本不应该捕获异常。

您应该只捕获您可以实际处理的异常。

请查看标签下的许多优秀问题:https://stackoverflow.com/questions/tagged/exception-handling?sort=votes

另外,请务必阅读 Microsoft 指南:“Design Guidelines for Exceptions”。

【讨论】:

    【解决方案2】:

    首先

    将捕获的异常包含为内部异常

    所以不是

    throw new ServiceException("", typeof(T).Name + rk + " data retrieval error");
    

    您应该设置内部异常。改变你的构造函数

    public ServiceException(string key, string message, Exception innerException)
                :base(message, innerException)
            {
                Errors = new Dictionary<string, string>(); 
                Errors.Add(key, message);
            }
    

    现在,

    //form  your exception message
     var message = typeof(T).Name + rk + " data retrieval error";
    //create service exception with the new overloaded constructor
     var exception  = new ServiceException("", typeof(T).Name + rk + " data retrieval error", message);
     throw exception;
    

    这将保留您的内部异常。

    【讨论】:

    • 感谢您的建议。我可以将 InnerException 作为构造函数参数传递吗?
    • @Matthias - 谢谢。我更新了我的代码,希望看起来没问题。
    • @Matthias - 刚刚尝试编译,我收到一条关于您的代码的错误消息:Error 2 Property or indexer 'System.Exception.InnerException' cannot be assigned to -- it is read only
    • InnerException 是只读属性。你不能设置它。我没有运行代码,因此没有意识到这一点。我现在已经更正了代码。请尝试一下。
    • 谢谢。我必须将“new innerException”更改为“innerException”才能编译。这是我所做的正确更改吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多