【问题标题】:SQL Array value for first item is being overwritten by the second item第一项的 SQL 数组值被第二项覆盖
【发布时间】:2014-08-12 18:16:07
【问题描述】:

我正在尝试构建一个系统,其中一个字母是从 2 个表中自动生成的。一张表格包含了这封信的所有内容,而另一张表格则列出了接收特定信件的人员。可能有多个人收到同一个字母,所以我尝试进行连接和循环以生成每个字母。

我的问题是我遇到从数组读取时返回的第一个值是数据库中的第二个条目。 IE 我应该有 (Rob, Jess, Alex) 输出,但我得到的是 (Jess, Jess, Alex)。

我不确定我的问题出在哪里。

SQL = "SELECT * FROM S.dbo.letters l INNER JOIN 
       S.dbo.ds d ON l.sID= d.sID
       WHERE l.id=@primaryID";

 SqlConnection dbconn = new SqlConnection(connStr);
 SqlCommand cmd = new SqlCommand(SQL, dbconn);

 dbconn.Open();
 cmd.Parameters.AddWithValue("@primaryID", 1);//Session["primIDedit"]

 SqlDataReader myReader = cmd.ExecuteReader();
 ArrayList letterInfo = new ArrayList();
 ArrayList dFname = new ArrayList();
 myReader.Read();

 while (myReader.Read())
 {

     dFname.Add(myReader["dfname"]);
     foreach (string i in dFname)
     {
     Label txtLabel1 = new Label(); //Generating a label
     txtLabel1.Text = i.ToString();
     ph1.Controls.Add(txtLabel1); //writing to a placeholder on the aspx page
     //for now I'm just wanting to return all values.
     }

     sName.Text = myReader[1].ToString() 
                  + " " + myReader[3].ToString() + " " + 
                  myReader[2].ToString();
     paragraph1.Text = myReader[9].ToString();
     paragraph2.Text = myReader[10].ToString();
     paragraph3.Text = myReader[11].ToString();
     signoff.Text = myReader[12].ToString();
}

【问题讨论】:

  • 能否简单解释一下这两个表中的相关列?你打算收到什么?
  • 您是否试图让代码变得神秘?使用SELECT * 然后myReader[n] 令人费解
  • 为什么要调用myReader.Read();在while循环之前?这将导致 wile 循环中的第一次迭代是数据读取器中的第二项,因为您已经调用了 Read()。
  • @TJ 这两张表是信件和捐助者。 sID 是我拥有的变量,用于对捐赠者进行分组,因此我可以将一封信发送给该组,但分为单个捐赠者。
  • @christiandev 为什么这令人费解?我应该提一下,这不是一个巨大的数据库,只有 14 列。我几乎使用了全部 14 个字母来生成字母,比你看到的那部分代码更多。

标签: c# sql arrays loops


【解决方案1】:

我在这里做了假设,但我会先创建两个类...

public class LetterInfo
{
   public List<Recipient> Recipients {get; set;}
   public string Paragraph1 {get; set;}
   public string Paragraph2 {get; set;}
   public string Paragraph3 {get; set;}
   etc

   public LetterInfo(){
    Recipients = new List<Recipient>();
   }
}

public class Recipient
{
   public string FirstName {get; set;}
   public string LastName {get; set;}
   public string MiddleName {get; set;}
}

然后,将您的数据库代码更改为如下所示...

using (Sqldbconn dbconn = new Sqldbconn(connStr))
    {
        string sql = "SELECT l.Field, d.field FROM S.dbo.letters l 
                INNER JOIN S.dbo.ds d ON l.sID= d.sID WHERE l.id=@primaryID";

        SqlCommand cmd = new SqlCommand(sql.ToString(), dbconn);
        cmd.Parameters.AddWithValue("@primaryID", 1);//Session["primIDedit"]

        dbconn.Open();

        LetterInfo letterInfo = new LetterInfo();
        var counter = 0;

        using (var rdr = command.ExecuteReader())
            {
                while (rdr.Read())
                {
                 var recipient = new Recipient();
                 recipient.FirstName = myReader["dfname"].ToString()
                 recipient.LastName = myReader["..."].ToString()
                 ....
                 letterInfo.Recipients.Add(recipient);

                 //only need to populate the letterinfo once.
                 if (counter == 0){
                     //use field name here, not the ordinal number
                     letterInfo.Paragraph1 = myReader[9].ToString();
                     letterInfo.Paragraph2 = myReader[10].ToString();
                     letterInfo.Paragraph3 = myReader[11].ToString();
                     ....
                  }

                     counter++;
                  }                   
            }
    }

然后您可以使用letterInfo 对象来填充您的表单。

你也可以把它移到某种数据帮助类中,然后从你的代码隐藏中调用 if...

public LetterInfo GetLetterInfo(int primaryId){
  //the code above in here
}

您的代码可能看起来像...

LetterInfo letter = dbHelper.GetLetterInfo(1);

p.s.我是用 Notepad++ 写的,所以我预计会出现编译错误 :)

【讨论】:

  • 谢谢你,我明天试试,看看我想出了什么。
  • @Jobokai,问题肯定是myReader.Read();,我已经在上面删除了-但您还应该考虑其他更改以使代码更具可读性:)
  • 所以我不得不进行一些调整,并且可能以比必要的更复杂的方式生成了这封信,但是由于您的代码和方法,我让一切正常。感谢您抽出时间来回答,我不确定我是否可以自己想出那个方法。
  • @Jobokai,没问题,很高兴它有帮助。
【解决方案2】:

在 while 循环之前删除这一行。

myReader.Read();

并在调试时使用断点检查 myreader 对象的下标值

 sName.Text = myReader[1].ToString() 
              + " " + myReader[3].ToString() + " " + 
              myReader[2].ToString();
 paragraph1.Text = myReader[9].ToString();
 paragraph2.Text = myReader[10].ToString();
 paragraph3.Text = myReader[11].ToString();
 signoff.Text = myReader[12].ToString();

【讨论】:

  • 我会尝试删除我的 reader.read,看看会发生什么。我有一种感觉,这是错误。
猜你喜欢
  • 1970-01-01
  • 2013-03-03
  • 1970-01-01
  • 1970-01-01
  • 2015-09-19
  • 2021-09-12
  • 2012-03-31
  • 2020-08-09
  • 1970-01-01
相关资源
最近更新 更多