当前位置:  开发笔记 > 编程语言 > 正文

C#using语句捕获错误

如何解决《C#using语句捕获错误》经验,为你挑选了5个好方法。

我只是看着使用声明,我一直都知道它的作用,但直到现在还没有尝试使用它,我已经提出了以下代码:

 using (SqlCommand cmd = 
     new SqlCommand(reportDataSource, 
         new SqlConnection(Settings.Default.qlsdat_extensionsConnectionString)))
 {
     cmd.CommandType = CommandType.StoredProcedure;
     cmd.Parameters.Add("@Year", SqlDbType.Char, 4).Value = year;
     cmd.Parameters.Add("@startDate", SqlDbType.DateTime).Value = start;
     cmd.Parameters.Add("@endDate", SqlDbType.DateTime).Value = end;
     cmd.Connection.Open();

     DataSet dset = new DataSet();
     new SqlDataAdapter(cmd).Fill(dset);
     this.gridDataSource.DataSource = dset.Tables[0];
 }

这似乎是工作,但有没有因为就在这个任何一点我可以告诉我还需要附上这在try catch块捕捉不可预见的错误,例如SQL服务器停机.我错过了什么吗?

据我目前所知,它只是阻止我关闭和处理cmd,但由于仍需要try catch,因此会有更多行代码.



1> Jason Jackso..:

在进行IO工作时,我编写了预期异常.

SqlConnection conn = null;
SqlCommand cmd = null;

try
{
    conn = new SqlConnection(Settings.Default.qlsdat_extensionsConnectionString)
    cmd = new SqlCommand(reportDataSource, conn);
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add("@Year", SqlDbType.Char, 4).Value = year;
    cmd.Parameters.Add("@startDate", SqlDbType.DateTime).Value = start;
    cmd.Parameters.Add("@endDate", SqlDbType.DateTime).Value = end;

        conn.Open(); //opens connection

    DataSet dset = new DataSet();
    new SqlDataAdapter(cmd).Fill(dset);
    this.gridDataSource.DataSource = dset.Tables[0];
}
catch(Exception ex)
{
    Logger.Log(ex);
    throw;
}
finally
{
    if(conn != null)
        conn.Dispose();

        if(cmd != null)
        cmd.Dispose();
}

编辑:为了明确,我在这里避免使用阻止因为我认为记录这样的情况很重要.经验告诉我,你永远不知道会出现什么样的奇怪异常.记录这种情况可能有助于您检测到死锁,或者发现架构更改会影响您使用少量且经过很少测试的部分代码库或任何其他问题.

编辑2:有人可以说,在这种情况下,一个使用块可以包装一个try/catch,这是完全有效的,在功能上是等效的.这真的归结为偏好.您是否希望以处理自己的处置为代价避免额外的嵌套?或者你是否需要额外的嵌套来进行自动处理.我觉得前者比较清洁,所以我这样做.但是,如果我在我工作的代码库中找到它,我不会重写后者.

编辑3:我真的,真的希望MS创建了一个更明确的using()版本,使其更加直观,真正发生的事情,并在这种情况下给予更多的灵活性.考虑以下虚构代码:

SqlConnection conn = null;
SqlCommand cmd = null;

using(conn = new SqlConnection(Settings.Default.qlsdat_extensionsConnectionString),
          cmd = new SqlCommand(reportDataSource, conn)
{
    conn = new SqlConnection(Settings.Default.qlsdat_extensionsConnectionString);
    cmd = new SqlCommand(reportDataSource, conn);
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add("@Year", SqlDbType.Char, 4).Value = year;
    cmd.Parameters.Add("@startDate", SqlDbType.DateTime).Value = start;
    cmd.Parameters.Add("@endDate", SqlDbType.DateTime).Value = end;
        cmd.Open();

    DataSet dset = new DataSet();
    new SqlDataAdapter(cmd).Fill(dset);
    this.gridDataSource.DataSource = dset.Tables[0];
}
catch(Exception ex)
{
    Logger.Log(ex);
    throw;
}

using语句只是在finally中使用Dispose()调用创建一个try/finally.为什么不给开发人员一个统一的处理和异常处理方式?


我只是意识到在尝试处理`Exception`时使用`using`的缺点.我同意@Jason Jackson.`using`在编译期间被翻译成`try/finally`.当我想捕获一个`Exception`时,将`try/catch`添加到`using`只会产生两个会影响性能的`try`子句.甚至最糟糕的是`.Dispose()`通常不会关闭连接,直到'.Close()'或等待垃圾收集.那么为什么不写'try/catch/finally'呢!我将检查null,连接打开以关闭并将其置于`final`块中.它更合适,更好.
所以我可以记录异常.在国家/地区的远程部分的用户桌面上的运行时异常中没有任何优雅,并且您不知道出了什么问题.
但明确处置与使用'使用'对于是否/如何记录异常完全没有影响.您可以轻松使用'using'块,并在'using'块内部有一个try块,用于执行操作,catch块用于记录异常.

2> TheSoftwareJ..:

此代码应如下所示,以确保及时关闭连接.仅关闭命令不会关闭连接:

using (SqlConnection con = new SqlConnection(Settings.Default.qlsdat_extensionsConnectionString))
using (SqlCommand cmd = new SqlCommand(reportDataSource, con))
         {
             cmd.CommandType = CommandType.StoredProcedure;
             cmd.Parameters.Add("@Year", SqlDbType.Char, 4).Value = year;
             cmd.Parameters.Add("@startDate", SqlDbType.DateTime).Value = start;
             cmd.Parameters.Add("@endDate", SqlDbType.DateTime).Value = end;
             cmd.Connection.Open();

             DataSet dset = new DataSet();
             new SqlDataAdapter(cmd).Fill(dset);
             this.gridDataSource.DataSource = dset.Tables[0];
         }

要回答您的问题,您可以在finally块中执行相同的操作,但这样可以很好地调整代码范围并确保您记得清理.


您没有告诉任何关于使用数据库连接捕获不可见错误的信息......

3> Michael Burr..:

using在这种情况下使用语句可能没有任何好处,如果你还是要使用try/ catch/ finallyblock.如您所知,该using语句是处理对象的try/的语法糖.如果你打算拥有自己的/ 无论如何,你当然可以自己做.finallyIDisposabletryfinallyDispose

这实际上主要归结为风格 - 您的团队可能更熟悉using语句或using语句可能使代码看起来更清晰.

但是,如果using声明隐藏的样板仍然存在,请继续自行处理,如果这是您的偏好.



4> jop..:

如果您的代码如下所示:

using (SqlCommand cmd = new SqlCommand(...))
{
  try
  {
    /* call stored procedure */
  }
  catch (SqlException ex)
  {
    /* handles the exception. does not rethrow the exception */
  }
}

然后我会重构它以使用try .. catch ..最后.

SqlCommand cmd = new SqlCommand(...)
try
{
  /* call stored procedure */
}
catch (SqlException ex)
{
  /* handles the exception and does not ignore it */
}
finally
{
   if (cmd!=null) cmd.Dispose();
}

在这种情况下,我将处理异常,所以我别无选择,只能添加try..catch,我不妨放入finally子句并保存自己另一个嵌套级别.请注意,我必须在catch块中执行某些操作,而不仅仅是忽略异常.



5> Kevin Haines..:

在阐述Chris Ballance所说的内容时,C#规范(ECMA-334第4版)第15.13节规定"使用声明被转换为三个部分:获取,使用和处置.资源的使用隐含在try语句中,其中包括finally子句.这个finally子句处理资源.如果获取了null资源,则不会调用Dispose,也不会抛出任何异常."

描述接近2页 - 值得一读.

根据我的经验,SqlConnection/SqlCommand可以通过多种方式生成错误,您几乎需要处理抛出的异常,而不是处理预期的行为.我不确定我是否想在这里使用using子句,因为我希望能够自己处理null资源的情况.

推荐阅读
殉情放开那只小兔子
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有