【问题标题】:Retrying method to call database重试调用数据库的方法
【发布时间】:2014-06-23 07:24:07
【问题描述】:

我正在制作一个应该 24/7 全天候运行的系统,并带有计时器来控制它。有许多对数据库的调用,在某些时候,有两种方法试图打开一个连接,其中一种会失败。我试图制作一个重试方法,所以我的方法会成功。在 Better way to write retry logic without goto 中的 Michael S. Scherotter 和 Steven Sudit 方法的帮助下,我的方法是否如下所示:

        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(.....)”处,出现异常:连接未关闭。连接的当前状态是打开的......这个问题是我尝试使用这种方法的原因!如果有人知道如何解决这个问题,请写信。谢谢

【问题讨论】:

    标签: c#


    【解决方案1】:

    你会的

     myCon.Open();
    

    在for循环中,但是

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

    在它之外。这样您就可以尝试多次打开同一个连接。如果你想防止数据库连接丢失,你需要把两者都放在循环中

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

        为新信息编辑

        如何使用 Transactions 来保持数据完整性,获取动态连接以进行多次访问并将它们包装在 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 语句的末尾时隐式完成。

        【讨论】:

        • 有些时候你理解得很好,有些时候你不明白。我已经在连接上使用单例。最后对我不起作用,因为它不仅是这个方法,而且假设有 20 个方法尝试继续连接到数据库,然后在某些时候两个方法同时连接。
        • 嗯,很有趣 - 您的系统是否在单独的线程/实例中运行?如果没有,那么您可以将 Singleton 替换为工厂类,然后分发新的数据库连接,这样就不会发生冲突?
        • 它们在单独的实例中运行。
        • 交易是一种选择吗?然后可以在 Using(var con = new SqlConnection(...)){} 块中放置多个连接,不再发生冲突,保持数据完整性,并且仍然可以从类实例访问数据库。
        • 我不知道具体怎么做?
        【解决方案4】:

        你有没有尝试添加

        myCon.Close();
        

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

        【讨论】:

          猜你喜欢
          • 2019-03-23
          • 2020-04-25
          • 1970-01-01
          • 2017-04-19
          • 1970-01-01
          • 1970-01-01
          • 2010-11-03
          • 2021-04-10
          • 1970-01-01
          相关资源
          最近更新 更多