c# - 在异常中捕获 "happy path"是一种不好的做法吗?

标签 c# sql error-handling try-catch

我有一个 SQL 语句来检查某个值是否在我的数据库中。如果该值不在数据库中,我想用“快乐路径”进行响应。 我发现使用 DbDataReader (.NET),如果 SELECT 查询找不到值,它会抛出异常 - 所以我的“快乐路径”最终会出现在异常中,而不是出现在主 try block 中。

我总是可以说“NOT IN”,但我不想返回数据库中没有该值的所有行 - 因为这会返回数千个结果,而我想要的只是一个“不,它不在这里”类型响应。

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 语句读取所有行相关的滞后。

是否有更好的方法来做到这一点,或者这种方法是否可以接受的最佳实践?

最佳答案

嗯,您不必获取所有记录到客户端;让我们为此提取一个方法。假设您使用 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);       
 }

请记住 - 异常(exception)适用于特殊情况。异常非常慢(堆栈展开需要资源);它们不可读 - 事实上,catch 是臭名昭著的 goto;它们是危险 - 在您当前的代码中,您捕获 太多异常:例如AccessViolationException 如果在 dbRunner.queryThis 中的某处抛出,将被有效屏蔽

关于c# - 在异常中捕获 "happy path"是一种不好的做法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56650279/

相关文章:

php - 如何在同一 mySQL 数据库中的表之间链接数据?

mysql - 连接使用 LIKE 作为公共(public)标识符的 2 个表

c# - 简单的Excel创建不会打开文件已损坏

json - Restful API - 带有单个或所有错误的 JSON 响应

c# - Resharper - 在进行代码清理时保留命名参数

c# - 使用 ANTLR 和 Antlr CSharp 目标为 DSL 构建编译器

javascript - Vue 获取发布数据到 Controller asp.net mvc

sql - 使用 union 将数据类型 varchar 转换为 bigint 时出错

java - 使用-Xmx内存参数可能会导致错误 "Could not create the Java virtual machine"

c# - 枚举集合被修改抵抗