2011-12-19 28 views
1

我正在制作一个应该全天候运行的系统,用定时器来控制它。对数据库有很多调用,并且在某些时候,有两种方法试图打开一个连接,其中一个会失败。我试图做一个重试方法,所以我的方法会成功。从迈克尔S. Scherotter和史蒂芬Sudit的方法Better way to write retry logic without 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; 

运行代码时,程序停止在了“(.....)”,和例外情况:连接未关闭。连接的当前状态是开放的......这个问题是我试图制作这种方法的原因!如果有人知道如何解决这个问题,请写信。由于

回答

0

编辑新的信息

怎么样使用事务保存数据完整性,获取多个访问的实时连接,并将它们封装在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语句结束时隐式完成。

+0

在某些时候,你理解得很好,有些则没有。我已经在连接上使用单身。最后不适用于我,因为它不仅仅是这个方法,而且让我们说20个方法连续地连接到数据库,然后在某个时候有两个方法同时连接。 – WildBoar 2011-12-19 12:19:53

+0

嗯有趣 - 你的系统运行在不同的线程/实例吗?如果没有,那么你可以用一个工厂类替换Singleton,然后发布新的数据库连接,这样就不会产生混淆? – 2011-12-19 12:21:45

+0

它们在单独的实例中运行。 – WildBoar 2011-12-19 12:33:31

2

你做

myCon.Open(); 

里面的for循环,但

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

在它之外。这样你就可以尝试多次打开相同的连接。如果你想防止DB连接丢失,你需要把两德循环内

0

您是否尝试过加入

myCon.Close(); 

进入一个Finally块。看起来如果你有例外情况,它永远不会被击中。我强烈建议你在Using声明中包装连接,命令对象等。这将确保它们被正确处置并且连接被关闭。

+0

我已经试过了最后的块,而且也没有工作。 – WildBoar 2011-12-19 12:00:34

1

您应该将呼叫转移到myCon.Open之外的语句或包裹myCon.Open()重新打开连接之前检查连接状态:

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