2011-12-19 5 views
1

Im создает систему, которая должна работать 24/7, с таймерами, чтобы управлять им. В базе данных много вызовов, и в какой-то момент два метода пытаются открыть соединение, и один из них будет терпеть неудачу. Я попытался сделать метод повтора, поэтому мои методы будут успешными. С помощью Майкла С. Scherotter и методы Стивена Судит в 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 (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(); 
    } 

Таким образом, даже если вы забыли закрыть соединение, он все равно будет сделано неявно, когда соединение доходит до конца своего Использование заявления.

+0

в какой-то момент вы это хорошо понимаете, а некоторые - нет. Я уже использую singleton в соединении. Наконец, это не работает для меня, потому что это не только этот метод, но и позволяет использовать 20 методов, пытающихся подключиться к базе данных, а затем в какой-то момент одновременно подключаются два метода. – WildBoar

+0

Hm interesting - ваша система работает в отдельных потоках/экземплярах? Если нет, то вы можете заменить Singleton на заводский класс и просто раздавать новые подключения к базе данных, таким образом, без коллизий? –

+0

Они работают в экземплярах separete. – WildBoar

2

Вы делаете

myCon.Open(); 

внутри для цикла, но

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

вне его. Таким образом вы пытаетесь открыть одно и то же соединение несколько раз. Если вы хотите защитить от потери связи DB вам нужно поместить как внутри Teh петли

0

Вы пытались добавить

myCon.Close(); 

в Finally блок. Похоже, он никогда не попадает, если у вас есть исключение. Я настоятельно рекомендую вам обернуть соединение, командный объект и т. Д. В операторы Using. Это обеспечит их правильное удаление и соединение будет закрыто.

+0

Я пробовал блок finally, и это тоже не сработало. – WildBoar

1

Вы должны переместить вызов myCon.Open вне для постановки или завернуть myCon.Open() проверка состояния соединения перед повторным открытием соединения:

if (myCon.State != ConnectionState.Open) 
{ 
    myCon.Open(); 
} 
Смежные вопросы