【问题标题】:Encountering a System.IndexOutOfRangeException: when trying to display data from two tables in a database遇到 System.IndexOutOfRangeException:尝试显示数据库中两个表中的数据时
【发布时间】:2022-01-22 20:07:16
【问题描述】:

我正在编写一个表单应用程序。用户在文本框中输入他的姓名、电子邮件、地址等,就好像他在订购包裹一样。如果用户已经下了订单,我想让用户可以在文本框中输入他的电子邮件,并根据他的电子邮件填写包裹所需的所有其他个人信息。

我遇到的麻烦是他的数据在两个不同的表中。 customer表中的数据(他的名字和姓氏)我已经成功检索到,但是表地址中的数据我不知道如何获取。

代码如下:

{
        try
        {
            var connection = getConnection();

            var command = new SqlCommand
            {
                Connection = connection,
                CommandText = "SELECT * FROM Customer WHERE Email = @Email"
            };

            command.Parameters.Clear();
            command.Parameters.AddWithValue("@Email", mailBox.Text);

            connection.Open();

            reader = command.ExecuteReader(CommandBehavior.SingleRow);

            if (reader.Read())
            {
                fnameBox.Text = reader["fname"].ToString();
                lnameBox.Text = reader["lname"].ToString();

                command.CommandText = "SELECT * FROM address WHERE customerID= "+ reader["customerID"].ToString();

                stateBox.Text = reader["state"].ToString();  //part where the error happens
                cityBox.Text = reader["city"].ToString();
                addressBox.Text = reader["address"].ToString();
                zipBox.Text = reader["zip"].ToString();

                int result = command.ExecuteNonQuery();
                connection.Close();

                if (result > 0)
                {
                    MessageBox.Show("Success");
                }
                else
                {
                    MessageBox.Show("Error");
                }
            }
            else
            {
                MessageBox.Show("E-mail entered doesn't exist");
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
} ```

【问题讨论】:

  • 另外,为什么你正确地参数化你的第一个语句,然后注入第二个?您显然知道参数化,那么为什么要在第二个查询中创建这样一个安全漏洞?
  • @Larnu 我已经收到了阅读那篇文章的建议,我确实做到了,但不幸的是,当我开始构建应用程序时,我不知道 AddWithValue() 的问题,现在我没有足够的是时候在我的截止日期前完成它了。这是一个学校项目,因此申请不必完美无缺。老实说,我真的不知道什么是参数化,我只是在网上找到了一堆代码,然后根据这些代码和我的教授给我的代码写了我的代码,哈哈。
  • 您不能在开始时只运行 1 个查询,即两个表的 SQL 连接吗? select c.fname, c.lname, a..state, a.city, a.address from customer c JOIN address a c.id = a.customerId 或类似。
  • @DaneBalia 我认为这可能是修复它的最佳方法。我尝试创建一个类似select c.fname,c.lname,c.Email, a.state,a.city,a.street, a.zip from customer c inner join address a on c.customerID = a.customerID where c.Email = 'mail@mail' 的 SQL 连接,现在它告诉我它找不到我尝试使用和不使用“”的所需电子邮件

标签: c# sql sql-server database forms


【解决方案1】:
  1. 考虑将来使用 EF 之类的东西,会清理这些东西,但感谢您在这里所做的事情可能不可行。
  2. 您应该通过 SQL 联接从多个表中获取相关数据(查看 LEFT JOIN 和 INNER JOIN)
  3. 您的问题是由没有state 字段的结果集引起的,而这又是由于您没有实际执行SELECT * FROM address 查询引起的-您正在设置命令文本但没有做任何进一步的事情。您需要为第二个查询创建另一个 DataReader 并读取 那些 结果。

总的来说,还有很多地方需要改进,但你显然还处于学习这方面的早期阶段,所以现在还好......

【讨论】:

  • 我尝试制作第二个 DataReader 但它给了我一个错误,它说它没有关闭或初始化 lol 。但我确实认为 CommandText 中的内部连接是可行的方法,也是另一个读者。感谢您的评论,如果您有任何其他可能有用的想法,我会尽力提供帮助。
  • 您可能还需要一个新的SqlCommand 对象,尽管我已经有一段时间没有做这些了。使用数据库时,如果可能,您应该始终尝试在数据库中进行所有过滤/搜索(WHERE)以获取相关数据(JOINS)和聚合(例如,bob smith 所做的所有订单的 SUM / COUNT / AVG);这就是现代 SQL 数据库的设计目的,因此它们擅长于此。
【解决方案2】:

你没有读完第一个结果,然后试图得到第二个

            command.Parameters.Clear();
            command.Parameters.AddWithValue("@Email", mailBox.Text);
           
            var customerID=0;
            var success=false;

            connection.Open();

            var reader1 = command.ExecuteReader();
              
            if (reader1.Read())
            {
               sucess=true;
                fnameBox.Text = reader1["fname"].ToString();
                lnameBox.Text = reader1["lname"].ToString();
                customerID=  Convert.ToInt32( reader1["customerID"].ToString());
            reader1.Close();
            }

      if( sucess)
       { 
              command.CommandText = "SELECT * FROM address WHERE customerID = @CustomerID";
             command.Parameters.Clear();
            command.Parameters.AddWithValue("@CustomerID", customerID);
            var reader2 = command.ExecuteReader();

            sucess=false;
            if (reader2.Read())
            {
                sucess=true;    
                stateBox.Text = reader2["state"].ToString();  
                cityBox.Text = reader2["city"].ToString();
                addressBox.Text = reader2["address"].ToString();
                zipBox.Text = reader2["zip"].ToString();
               reader2.Close();
             }
            if (success)
                {
                    MessageBox.Show("Success");
                }
                else
                {
                    MessageBox.Show(" address select Error");
                }
      }
       else
      {
                MessageBox.Show("E-mail entered doesn't exist");
      }
                connection.Close();

【讨论】:

  • 感谢您的评论,但您发送的代码不起作用,即使使用您的代码,我仍然得到相同的结果。只有客户的名字和姓氏被填写,其余数据不填写。
  • @LukaPrcic 我添加了 reader.Close 到我的代码。如果仍然无法正常工作,请使用调试器检查您的命令参数值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多