【问题标题】:Try-Catch and "Continue" - is this possible?Try-Catch 和“继续”——这可能吗?
【发布时间】:2011-05-26 23:29:20
【问题描述】:

我的代码中有一个部分用于查询网络上的所有 SQL Server 数据库。我首先尝试使用 SQL 登录来访问 SQL Server 实例,但如果失败,那么我想尝试使用我的 Windows 凭据进行连接。之后,如果我仍然无法连接,那么我希望代码失败,然后通知用户。

所以我想我要问的是如何从 Try-Catch 块内部循环到 Try-Catch 块上方的行:

String conxString = @"Data Source=SQLInstance1;User ID=FOO;Password=BAR;";
bool secondTime = false;

using (SqlConnection sqlConx = new SqlConnection(conxString))
     {
         Try{
               sqlConx.Open();
               DataTable tblDatabases = sqlConx.GetSchema("Databases");
               sqlConx.Close();
               secondTime = false;
               Console.WriteLine("SQL Server found!");
         }
         Catch(System.Data.SqlClient.SqlException e){
                if (!secondTime){
                   secondTime = true;
                   conxString = @"Data Source=SQLInstance1; Integrated Security=True;";
                      //Loop back to the using statement to try again with Windows Creds
                {
                 else{
                   Console.WriteLine("SQL Server not found or credentials refused");
                 }
                   //Report Failure to connect to user

         }
         finally{
            //Reset Variable
            secondTime = false;
         }

      }

【问题讨论】:

  • @Abe - 这就是我添加 secondTime 标志的原因,这样它只会循环一次。
  • 只是一般性评论,我认识的大多数开发人员都会反对使用异常进行代码分叉。异常应该显示或记录错误消息,然后留下出错的代码。将生产力代码放在一个 catch 块中确实混淆了关注的领域。

标签: c# .net try-catch


【解决方案1】:

我可能会走这条路:

String conxString = @"Data Source=Instance1;User ID=FOO;Password=BAR;";
//in your main function
if(!TryConnect(conxString))
{
   Console.WriteLine("SQL Creditials failed.  Trying with windows credentials...");
   conxString = "new conn string";
   TryConnect(conxString);
}
..............
//new function outside of your main function
private bool TryConnect(string connString)
{
   using (SqlConnection sqlConx = new SqlConnection(conxString))
     {
         Try{
               sqlConx.Open();
               DataTable tblDatabases = sqlConx.GetSchema("Databases");
               sqlConx.Close();
         }
         Catch(System.Data.SqlClient.SqlException e){
                return false;
         }
         return true;    
      }
}

【讨论】:

  • 我从来没有想过,好主意!
  • 我会说这是最好的答案。它简单、有效,并且解决了所提出的问题。
  • 看了这个解决方案后,我发现这是一个比使用 GoTo 更好的解决方案。谢谢大家的建议和cmets。
【解决方案2】:

成功后,您可以使用for 循环和break:

for (int attempt = 1; attempt <= 2; attempt++)
{
    try
    {
        /* perform attempt */
        var success = TryToConnect();
        if (success)
            break;
    }
    catch (Exception e)
    {
        /* report error */
    }
}

您还可以记录是否成功等或增加尝试次数或使尝试次数可配置。

【讨论】:

  • +1 回答。始终从零开始索引for (int attempt = 0; attempt &lt; 2; attempt++)。 `
  • @Xaqron:我选择使用基于 1 的变量的原因是,稍后在代码中我们可以说 if (attempt == 2) 表示英文 这是第二次尝试吗?。但我同意从零开始也是一个明智的选择。
  • 不过,我认为目标是在尝试之间更改连接字符串,是吗?
  • @EoRaptor013:抱歉,我的伪代码没有明确指出变量attempt 可用于更改连接尝试。我之前的评论描述了如何在伪代码上粘贴代码时使用attempt == 2 代替secondTime。
【解决方案3】:

此blog post(尽管是从 2005 年开始)显示了您的问题的可能解决方案:

使用转到

TryLabel:
try
{
    downloadMgr.DownLoadFile("file:///server/file", "c:\\file");
    Console.WriteLine("File successfully downloaded");
}
catch (NetworkException ex)
{
    if (ex.OkToRetry)
        goto TryLabel;
}

写一个包装器

public static bool Wrapper(DownloadManager downloadMgr)
{
    try
    {
        downloadMgr.DownLoadFile("file:///server/file", "c:\\file");
        return true;
    }

    catch (NetworkException ex)
    {
        Console.WriteLine("Failed to download file: {0}", ex.Message);
        return (!ex.OkToRetry);
    } 
}

static void Main(string[] args)
{
    while (!Wrapper(downloadMgr)) ;
}

【讨论】:

  • “goto”不只是带回有趣的回忆吗?
  • 你这么说很有趣,在我的 VB6 项目中,我会做类似 Resume TryBlockAgain: 或类似的事情。
  • 很抱歉,每当我在现代代码中看到 goto 时,我仍然痛苦地尖叫。
  • GoTo 的使用如何获得最佳答案??? GoTo 是对我所有编程敏感性的侮辱。说真的,Stack-O 需要设置一个最少 24 小时的时间,作者才能将答案标记为正确。
  • @MikeTeeVee - 这是我需要编写的一个快速而肮脏的应用程序,以便我可以在 250 多个不同的 SQL Server 实例中搜索特定数据库。虽然它可能不漂亮,但它完成了它的设计目的,我能够找到我正在寻找的服务器。
猜你喜欢
  • 2013-11-25
  • 2012-06-04
  • 1970-01-01
  • 2019-06-19
  • 2021-01-22
  • 2011-11-17
  • 2014-11-27
  • 2013-02-08
  • 2011-11-19
相关资源
最近更新 更多