重试调用数据库的方法

本文关键字:方法 数据库 调用 重试 | 更新日期: 2023-09-27 18:18:21

我正在制作一个应该24/7运行的系统,用计时器来控制它。有许多对数据库的调用,并且在某些时候,有两个方法试图打开连接,其中一个将失败。我已经尝试了一个重试方法,所以我的方法会成功。在Michael S. Scherotter和Steven Sudit的方法的帮助下,在没有goto的情况下更好地编写重试逻辑,我的方法看起来像这样吗:

        int MaxRetries = 3;
        Product pro = new Product();
        SqlConnection myCon = DBcon.getInstance().conn();
        string barcod = barcode;
        string query = string.Format("SELECT * FROM Product WHERE Barcode  = @barcode");
        for (int tries = MaxRetries; tries >= 0; tries--) //<-- 'tries' at the end, are unreachable?. 
        {
            try
            {
                myCon.Open();
                SqlCommand com = new SqlCommand(query, myCon);
                com.Parameters.AddWithValue("@barcode", barcode);
                SqlDataReader dr = com.ExecuteReader();
                if (dr.Read())
                {
                    pro.Barcode = dr.GetString(0);
                    pro.Name = dr.GetString(1);
                }
                    break;
                }
                catch (Exception ex)
                {
                    if (tries == 0)
                        Console.WriteLine("Exception: "+ex);
                        throw;
                }
                }

        myCon.Close();
        return pro;

运行代码时,程序在"for(.....)"处停止,并出现异常:连接未关闭。连接的当前状态是打开的…这个问题就是我为什么要尝试这个方法的原因!如果有人知道如何解决这个问题,请写信。由于

重试调用数据库的方法

你可以

 myCon.Open();

在for循环中,但是

  myCon = DBcon.getInstance().conn();

在它外面。通过这种方式,您可以多次打开同一个连接。如果你想防止DB连接丢失,你需要把它们都放在循环中

您应该将调用移到for语句之外的myCon.Open或包装myCon.Open()在重新打开连接之前检查连接状态:

if (myCon.State != ConnectionState.Open)
{
   myCon.Open();
}

编辑新信息

如何使用事务来保持数据完整性,获得多访问的动态连接,并将它们包装在using语句中以确保连接关闭?如

        Using (SqlConnection myCon = new SqlConnection('ConnectionString'))
        {
          myCon.Open();
          var transaction = myCon.BeginTransaction();    
          try 
          { 
            // ... do some DB stuff - build your command with SqlCommand but use your transaction and your connection
           var sqlCommand = new SqlCommand(CommandString, myCon, transaction);
           sqlCommand.Parameters.Add(new Parameter()); // Build up your params
           sqlCommand.ExecuteNonReader(); // Or whatever type of execution is best
           transaction.Commit();  // Yayy!
        } 
        catch (Exception ex) 
        { 
            transaction.RollBack();  // D'oh!
            // ... Some logging
        } 
        myCon.Close();
    }

这样,即使您忘记关闭连接,当连接到达Using语句的末尾时,它仍然会隐式地完成。

是否尝试添加

myCon.Close();

放到Finally块中。如果你有一个异常,它看起来永远不会被击中。我强烈建议您在Using语句中包装连接、命令对象等。这将确保它们被正确地处理并关闭连接。