【问题标题】:SqlDataReader causes the webpage not to loadSqlDataReader 导致网页无法加载
【发布时间】:2013-06-24 20:48:24
【问题描述】:

我正在使用数据库将部门名称与其唯一的邮寄代码相关联,即会计有邮寄代码 1337。ShortName 和 ID 是正在查询的数据库字段。

架构是

  • ID int
  • ShortName nvarchar(255)

这是使用 C# 在网页的后端完成的。我在同一代码的其他地方使用了SqlDataReader 对象,但没有由此引起错误。我想我在某处有语法错误,或者我试图将一个字符串插入一个 int 或一些愚蠢的东西,但我看不到它。

SqlConnection 设置正确,因为它用于页面加载时的查询,并且在指示的行被注释掉时工作。

SqlDataReader SQl_Reader;
string cmdString = "SELECT ShortName FROM departments WHERE (ID = " +
  department_Text.SelectedValue.ToString() + ")"; //a selected value in department_text would be the mailing code such as 1337, or 1304.

SqlCommand SQl_Command2 = new SqlCommand(cmdString, SQl_Connection);

SQl_Reader = SQl_Command.ExecuteReader();

string deptName = SQl_Reader["ShortName"].ToString();//This should assign the deptName = the value in SQl_Reader but it causes the page not to load. Not sure what is wrong with it

SQl_Reader.Close();
SQl_Connection.Close();

我已经尝试了多种不同的方法,即使只为此查询使用专有的连接、命令和阅读器。我已经将SqlDataReader 用于类似目的,在代码的另一个函数中使用相同的两个字段,并且效果很好。任何见解将不胜感激。

【问题讨论】:

  • 您在这段代码中有一个非常严重的 sql 注入漏洞。您需要改为使用参数化查询。 department_Text 的值很可能不是您认为的那样,并且查询没有返回任何结果,因此当您在空引用上调用 ToString() 时会引发异常。
  • 在阅读任何内容之前不应该调用 SQL_Reader.Read() 吗?

标签: c# sql sql-server


【解决方案1】:

如果您要使用阅读器,则需要在获取值之前调用Read()

如果你想要一个单一的值,那么你最好改用ExecuteScalar()

还可以使用参数化查询来防止 SQL 注入(以及其他好处)..

    SqlDataReader SQl_Reader;
    string cmdString = "SELECT ShortName FROM departments WHERE ID = @ID;"
    SqlCommand SQl_Command2 = new SqlCommand(cmdString, SQl_Connection);
    SQl_Command2.Parameters.Add("@ID", department_Text.SelectedValue);
    SQl_Reader = SQl_Command.ExecuteReader();
    SQl_Reader.Read();
    string deptName = SQl_Reader["ShortName"].ToString();

    SQl_Reader.Close();
    SQl_Connection.Close();

或更好..

    SqlDataReader SQl_Reader;
    string cmdString = "SELECT ShortName FROM departments WHERE ID = @ID;"
    SqlCommand SQl_Command2 = new SqlCommand(cmdString, SQl_Connection);
    SQl_Command2.Parameters.Add("@ID", department_Text.SelectedValue);
    SQl_Reader = SQl_Command.ExecuteReader();
    SQl_Reader.Read();
    string deptName = SQl_Command.ExecuteScalar() as String;

    SQl_Reader.Close();
    SQl_Connection.Close();

【讨论】:

    【解决方案2】:

    您需要先从 SQl_Reader 中读取 .Read() ,然后它才会有任何数据。 通常你会这样做

    While (SQl_Reader.Read() )
    {
       // Get values here
    }
    

    如果您确定只会返回一行,那么您应该将查询更改为

    Select top 1 ShortName FROM 
    

    但您仍然需要 Read()。我也同意关于对注入攻击持开放态度的评论。您需要将 department_Text.SelectedValue 作为查询参数传入

    【讨论】:

      【解决方案3】:

      我假设 ID 是主键,因此特定 ID 没有其他可能的值,那么 ExecuteScalar 将完成这项工作。

      string cmdString = "SELECT ShortName FROM departments WHERE (ID = @depId)";
      
      using (SqlCommand SQl_Command2 = new SqlCommand(cmdString, SQl_Connection))
      {
          //a selected value in department_text would be the mailing code such as 1337, or 1304.
          SQl_Command2.Parameters.Add("@depId", System.Data.SqlDbType.Int).Value = department_Text.SelectedValue;
      
          string deptName = (string)SQl_Command2.ExecuteScalar();
      }
      

      不要忘记使用SqlCommand.Parameters Property 代替字符串连接。

      我最好使用using 来自动处理对象,更多信息:Is SqlCommand.Dispose() required if associated SqlConnection will be disposed?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-01-03
        • 2023-04-09
        • 2016-03-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多