1

故事:我有来自 3 个不同类的 3 个函数。函数调用顺序为:

Form1_Load(...) -> Student.GetAllStudents(...) -> StudentDAL.GetStudentInformation(...) -> ConnectionManager.GetConnection(...)

我想做的是显示最内部函数的 StackTrace,即ConnectionManager.GetConnection()Form1 类MessageBox中。换句话说,我不想在任何内部类中使用,而只想在最外面的类中使用Form1 类MessageBox

问题:要获取内部异常,我们可以使用InnerExceptionorGetBaseException()等​​,但是当我尝试获取内部异常时,它会抛出异常“对象引用未设置为实例”,这意味着没有内部异常,当我检查时,值为也null。我只想知道为什么会这样null?它不应该引用内部异常吗?如我错了请纠正我。

功能代码:

  1. Form1_Load(...)

    private void Form1_Load(object sender, EventArgs e)
          {
               try
               {
                    DataTable dt = new DataTable();
                    dt.Load((**new Student().GetAllStudents()**));
                    if (dt.Rows.Count <= 0)
                    {
                         MessageBox.Show("Student table empty.");
                    }
                    else
                    {
                         this.dataGridView1.DataSource = dt;
                    }
               }
               catch (Exception ex)
               {
                    MessageBox.Show(ex.Message+Environment.NewLine+"Source(s) : "+ex.StackTrace.Substring(0, ex.StackTrace.LastIndexOf("at")));
               }
    
  2. GetAllStudents(...)

    public SqlDataReader GetAllStudents()
          {
               try
               {
                    return StudentInformationDataAccessLayer.GetStudentInformation();
               }
               catch (Exception ex)
               {
                    throw ex;
               }
          }
    
  3. GetStudentInformation(...)

    public static SqlDataReader GetStudentInformation()
          {
               try
               {
                    SqlConnection sqlCon = null;
                    sqlCon = ConnectionManager.GetConnection();
                    if (sqlCon == null)
                    {
                         return null;
                    }
                    String Query = null;
                    Query  = "SELECT * FROM [dbo].[Student]";
                    SqlCommand cmd = new SqlCommand(Query, sqlCon);
                    SqlDataReader dr = null;
                    dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
                    return dr;
               }
               catch (Exception ex)
               {
                    throw ex;
               }
          }
    
  4. GetConnection(...)

    public static SqlConnection GetConnection()
          {
               String _connectionString = null;
               _connectionString = ConfigurationManager.ConnectionStrings["Default"].ConnectionString;
    
               if (_connectionString == null)
               {
                    return null;
               }
    
               try
               {
                    SqlConnection connection = new SqlConnection(_connectionString);
                    connection.Open();
                    return connection;
               }
               catch (Exception ex)
               {
                    throw ex;
               }
          }
    
4

4 回答 4

2

如果您希望保留堆栈跟踪和异常信息,您应该更改重新抛出捕获的异常的代码,如下所示:

 }
 catch(Exception ex)
 {
     // do what you need to do with ex
     // ..
     // rethrow..

     throw;           // notice this is not "throw ex";
 }

使用 just 重新抛出异常会throw;保留原始堆栈跟踪。不一定会有内部异常,但这不是您应该关心的。您需要知道的是异常起源的堆栈跟踪。

于 2013-11-16T19:37:42.843 回答
1

如果您想重新抛出内部异常集,请使用以下代码,但请记住您将丢失堆栈跟踪

try
{
   ...
}
catch (Exception ex)
{
  throw new Exception("message", ex);
}

要重新抛出异常并保留堆栈跟踪,请使用:

try
{
   ...
}
catch (Exception ex)
{
  throw;
}
于 2013-11-16T19:35:12.840 回答
1

并非每个异常实际上都有内部异常。首先检查内部 ex 是否为 a null,如果不是则处理它。

话虽如此,您当然可以重新抛出您的异常,如下所示:

catch(Exception ex)
 {
     // so smth
     // ..
     // rethrow..

     throw;          
 }

但请记住两点:

  1. 不要打字throw ex,只要throw

  2. 仅当您真的想在重新抛出之前对这个异常做一些事情时才这样做。如果你没有这样的计划,就不要在这个层面上抓住它。

于 2013-11-16T19:35:55.830 回答
0

我会做类似的事情:

try
{
  ...
}
catch (Exception ex)
{
  if (ex.InnerException == null)
    throw ex;
  else
    throw ex.InnerException;
}

然后在您想要进行堆栈跟踪的某个时候,按照以下方式进行操作:

StackTrace trace = new StackTrace(System.Threading.Thread.CurrentThread, true);
StackFrame[] frames = trace.GetFrames();
string result = string.Empty;
foreach (StackFrame sf in frames)
{
  string += sf.GetMethod().Name;
}
MessageBox(result);
于 2013-11-16T19:47:29.020 回答