【问题标题】:Getting Error: Not all code paths a value出现错误:并非所有代码路径都有值
【发布时间】:2016-10-07 00:15:45
【问题描述】:
public bool loginpro(string loginas, string dept, string usnm, string pass)
{
    try
    {
        string qrstr;
        qrstr = "select * from login where loginas=='" + loginas + "',dept=='" + dept + "',usnm=='" + usnm + "',pass=='" + pass + "'";
        Gencon.Open();
        SqlCommand cmd = new SqlCommand(qrstr, Gencon);
        SqlDataAdapter da = new SqlDataAdapter(cmd);
        DataTable dt = new DataTable();
        da.Fill(dt);
        Gencon.Close();
        if (dt.Rows.Count > 0)
        {
            return true;
        }


    }
    catch (Exception e)
    {
        return false;
    }
}

【问题讨论】:

  • 如果 Rows.Count 为零怎么办?你有返回值吗?编译器(和 C# 规则)对此并不满意。
  • 没有行需要返回false
  • 顺便说一句,在解决了这个问题后,由于多种原因,您的查询完全错误。 == 是 C# 运算符,不是 SQL,WHERE 多个条件要用逻辑运算符连接,sql 文本是 Sql Injection 方。

标签: c# sql sqlcommand


【解决方案1】:

问题出在 try 块中,try 块只有在 DataTable 有行时才返回值,如果没有行怎么办?

if (dt.Rows.Count > 0)
{
    return true;
}
else
{
    // has to return something.
    return false; 
}

或者你可以用这个来简化

return dt.Rows.Count > 0 ;  // assuming in else you want to return false.

【讨论】:

  • 如果我想抛出异常捕获块然后在 else 块中?
【解决方案2】:

你的代码有很多问题。当然编译器会在编译时阻止你,但是你会在运行时遇到其他错误

所以修复编译时问题很容易。如果您的查询没有返回任何行,只需编写一个返回值:

    // This returns true if you have rows, false if not
    return (dt.Rows.Count > 0);

现在您在运行时将面临的问题如下

  • SQL 中的等号运算符是 = 而不是 ==
  • 多个 WHERE 条件应由逻辑运算符连接 (AND, OR)
  • sql 文本应参数化

public bool loginpro(string loginas, string dept, string usnm, string pass)
{
    try
    {
        string qrstr;
        qrstr = @"select * from login where loginas=@login and dept = @dept
                 and usnm = @user and pass= @pass";
        Gencon.Open();
        SqlCommand cmd = new SqlCommand(qrstr, Gencon);
        cmd.Parameters.Add("@login", SqlDbType.NVarChar).Value = loginas;
        cmd.Parameters.Add("@dept", SqlDbType.NVarChar).Value = dept;
        cmd.Parameters.Add("@user", SqlDbType.NVarChar).Value = usnm;
        cmd.Parameters.Add("@pass", SqlDbType.NVarChar).Value = pass;
        SqlDataAdapter da = new SqlDataAdapter(cmd);
        DataTable dt = new DataTable();
        da.Fill(dt);
        Gencon.Close();
        return (dt.Rows.Count > 0);
    }
    catch (Exception e)
    {
        Gencon.Close();
        return false;
    }
}

还有其他问题,例如不使用 using statement 并尝试传递一个清晰的 text password to your database 引擎,这可能会导致内存泄漏和安全问题。

【讨论】:

    【解决方案3】:

    错误的直接原因是如果您有零行,.Net 不知道要返回什么值

      ...
      if (dt.Rows.Count > 0)
      {
           return true;
      }
      ...
      // what should be returned? true or false?
    

    我建议将方法重写为这样的:

    public bool loginpro(string loginas, string dept, string usnm, string pass) {
      //DONE: Make SQL readable; debug it ( "=" instead of "==" )
      //DONE: Do not fetch redundant data (select * ...) 
      //DONE: Make SQL parametrized  
      String sql = 
        @"select 1
            from login
           where loginas = @prm_loginas and 
                 dept = @prm_ dept and
                 usnm = @prm_user and 
                 pass = @pass"; //TODO: do not store password, but its hash value
      try { 
        //DONE: wrap IDisposable into using
        //DONE: do not use global SQL connections Gencon.Open()...Gencon.Close()
        using (SqlConnection con = new SqlConnection(connectionStringHere)) {
          con.Open();
    
          //DONE: wrap IDisposable into using
          using (SqlCommand cmd = new SqlCommand(sql, con)) {
            cmd.Parameters.Add("@prm_loginas", SqlDbType.NVarChar).Value = loginas;
            cmd.Parameters.Add("@prm_ dept", SqlDbType.NVarChar).Value = dept;
            cmd.Parameters.Add("@prm_user", SqlDbType.NVarChar).Value = usnm;
            //TODO: do not pass password! Pass hash value instead
            cmd.Parameters.Add("@pass", SqlDbType.NVarChar).Value = pass;
    
            //DONE: wrap IDisposable into using
            //DONE: do not fetch redundant data (you want at most one record only) 
            using (var reader = cmd.ExecuteReader()) {
              return reader.Read(); // <- cursor has at least one record
            }
          }  
        }
      }
      catch (DbException ee) { //DONE: do not catch all the exceptions
        return false;
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-07-01
      • 2014-04-16
      • 2015-02-07
      • 2012-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      • 1970-01-01
      相关资源
      最近更新 更多