如何从SqlDataReader返回单个值?

6

我在单层应用程序中忘记返回值了。

public  int Studentid()
    {
        try
        {
            SqlConnection con = new SqlConnection(connectionStr);
            SqlCommand cmd = new SqlCommand("SELECT s_id FROM student where name = + ('" + Request.QueryString.ToString() + "')", con);
            con.Open();
            SqlDataReader dr = null;
            con.Open();
            dr = cmd.ExecuteReader();
            if (dr.Read())
            {
                //Want help hear how I return value
            }

            con.Close();
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

请查看 msdn - oleksii
如果学生姓名是 Request.QueryString.ToString,我想返回 s_id。就这些了。谢谢。 - 4b0
有没有人会向@ShreeKhanal展示如何避免SQL注入漏洞? - quentin-starin
@qes:好观点。我会把它加入到我的回答中。 - Guffa
7个回答

21

这是一个可以实现你想要功能的方法的版本。

public int GetStudentId()
{
    var sql = string.Format("SELECT s_id FROM student where name = '{0}'", Request.QueryString);
    using (var con = new SqlConnection(connectionStr))
    using (var cmd = new SqlCommand(sql, con))
    {
        con.Open();
        var dr = cmd.ExecuteReader();
        return dr.Read() ? return dr.GetInt32(0) : -1;
    }
}

当你除了重新抛出异常之外不执行任何与异常相关的操作时,没有必要使用try/catch(实际上,使用throw ex;而不是throw;会导致原始堆栈跟踪丢失)。 另外,C#的using语句可以用更少的代码清理资源。

重要提示

直接将查询字符串传递给SQL意味着任何人都可以在您的数据库中执行随机SQL,潜在地删除所有内容(或更糟)。 请阅读有关SQL注入的文档。


我们不关闭 SqlConnection,可以吗? - Julius Prayogo
1
@JuliusPrayogo,这不是世界末日,但你应该关闭它。如果你不这样做,垃圾收集器将在稍后的某个时刻关闭它,但这可能会导致问题,如连接对象耗尽。我想不到不关闭它的好理由,你呢? - Drew Noakes

4

您应该使用using块,以确保连接、命令和阅读器正确关闭。然后,您可以从if语句内部返回值,而不必将其存储在变量中,直到关闭对象为止。

您只需要打开一次连接。

您应该使用参数化查询,而不是将值连接到查询中。

public  int Studentid() {
  try {
    using (SqlConnection con = new SqlConnection(connectionStr)) {
      using (SqlCommand cmd = new SqlCommand("SELECT s_id FROM student where name = @Name", con)) {
        cmd.Parameters.Add("@Name", DbType.VarChar, 50).Value = Request.QueryString.ToString();
        con.Open();
        using (SqlDataReader dr = cmd.ExecuteReader()) {
          if (dr.Read()) {
            return dr.GetInt32(0);
          } else {
            return -1; // some value to indicate a missing record
            // or throw an exception
          }
        }
      }
    }
  } catch (Exception ex) {
    throw; // just as this, to rethrow with the stack trace intact
  }
}

3

最简单的返回单个值的方法是调用ExecuteScalar。您还应该修复SQL注入漏洞。你是想编码整个查询字符串数组,还是只挑选一个单独的值?

public int StudentId()
{
    string sql = "SELECT s_id FROM student WHERE name = @name";
    using (var con = new SqlConnection(connectionStr))
    {
        using (var cmd = new SqlCommand(sql, con))
        {
            cmd.Parameters.Add("@name", DbType.VarChar, 256).Value = Request.QueryString["name"];
            con.Open();
            return (int)cmd.ExecuteScalar();
        }
    }
}

2

试试这个:

int s_id = (int) dr["s_id"];

1
int studId=0;
if(rdr.Read())
{
  studId=rdr.GetInt32(rdr.GetOrdinal("s_id"));
}

0
 if (dr.Read())
            {
                //Want help hear how i return value
                int value = dr.GetInt32("s_id");
            }

-1

像这样吗?

public  int Studentid()
{
        int studentId = -1;
        SqlConnection con = null;
        try
        {
            con = new SqlConnection(connectionStr);
            SqlCommand cmd = new SqlCommand("SELECT s_id FROM student where name = + ('" + Request.QueryString.ToString() + "')", con);
            SqlDataReader dr = null;
            con.Open();
            dr = cmd.ExecuteReader();
            if (dr.Read())
            {
                studentId = dr.GetInt32(0);
            }

            dr.Close();

        }
        catch (Exception ex)
        {
            throw ex;
        }
        finally
        {
            if(con != null)
                 con.Close();
            con = null;
        }

       return studentId;
 }

2
我知道你只是复制了他的代码然后进行了修改,但是在这个过程中复制了他所有的错误,所以扣1分。 - John Saunders

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接