Это плохая практика, чтобы поймать «счастливый путь» в исключении? - PullRequest
2 голосов
/ 18 июня 2019

У меня есть оператор SQL, который проверяет, есть ли значение в моей базе данных или нет.Я хочу ответить "счастливым путем", если значение не в базе данных.Используя DbDataReader (.NET), я обнаружил, что если запрос SELECT не может найти значение, он выдает исключение - поэтому мой «счастливый путь» заканчивается в исключении, а не в основном блоке try.

Я всегда могу сказать «НЕ В», но я не хочу возвращать все строки в базе данных, которые не имеют значения - так как это вернет многие тысячи результатов, где все, что я хочу, это просто «нет»«здесь нет» типа ответа.

public void wristbandScan(string barcode)
    {
        string query = "SELECT ticket FROM tickets WHERE 
                             linked_barcode='" + barcode + "'";

        ValidTicketEventArgs args = new ValidTicketEventArgs();

        try
        {
            var queryResult = _dbRunner.queryThis(query);

            args.Result = false;
            args.Message = "WB already linked";
            args.Barcode = barcode; 
            OnValidTicketEvent(args);
        }
        catch (Exception e)
        {
            this.updateWristband(barcode);
            this.updateValid();
            args.Result = true;
            args.Message = "WB linked";
            args.Barcode = barcode;
            OnValidTicketEvent(args);
        }
    }

Мне кажется неправильным отлавливать счастливый путь в операторе ошибки, но я не хочу отставание, связанное с чтением во всех строках с помощью оператора NOT IN.

Есть ли лучший способ сделать это или этот подход является приемлемой наилучшей практикой?

Ответы [ 2 ]

2 голосов
/ 18 июня 2019

Ну, вам не нужно доставать все записи клиенту; давайте извлечем метод для этого. Предполагая, что вы работаете с MS Sql:

 public bool hasScanCode(string barcode) {
   if (string.IsNullOrWhiteSpace(barcode)) 
     return false;

   //DONE: paramterize queries 
   string query = 
      @"SELECT ticket 
          FROM tickets 
         WHERE linked_barcode = @prm_BarCode";

   using (var conn = new SqlConnection(connection_string_here)) {
     conn.Open();

     using (var q = new SqlCommand(conn, query)) {
       //TODO: q.Parameters.Add is a better choice
       q.Parameters.AddWithValue("@prm_BarCode", barcode.Trim()); 

       using (var reader = q.ExecuteReader()) {
         // we read (fetch) at most 1 record
         // if empty cursor - no record with given barcode 
         return reader.Read(); 
       }
     }
   }
 }

тогда мы можем использовать его:

 public void wristbandScan(string barcode) {
   bool result = hasScanCode(barcode); 

   ValidTicketEventArgs args = new ValidTicketEventArgs() { 
     Result = result,
     Message = result ? "WB linked" : "WB already linked",
     Barcode = barcode, 
   };  

   OnValidTicketEvent(args);       
 }

Пожалуйста, помните - исключения для исключительные ситуации . Исключения очень медленные (для развертывания стека требуются ресурсы); они не читабельны - catch, фактически работают как пресловутые goto; они опасны - в вашем текущем коде вы catch слишком много исключений : например, AccessViolationException, если он брошен где-то в пределах dbRunner.queryThis, будет эффективно в маске .

0 голосов
/ 18 июня 2019

Создайте и вызовите StoredProcedure, который может обрабатывать пустую ситуацию и не возвращать строки вместо исключения.

Затем обработайте сценарий без строк за пределами try/catch.

...