简体   繁体   中英

SqlDataReader not reading any row apart from first

New to stackoverflow and very much ac# beginner

Currently creating a form which produces a bar chart from data stored in a database. The chosen record is identified by pID (patient's ID) and tdate (Test date). These values are determined by 2 combo boxes that the user can select from, The problem I am having is that only the first and last records stored in the database are populating the barchart.

 if (radioButtonTestResult.Checked)
{
foreach (var series in TestResultBarChart.Series)
{
series.Points.Clear();
}
string tdate = comboBox2.Text;
using (SqlConnection connection = new SqlConnection(@"Data Source=               (LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\MMSEDB.mdf;Integrated    Security=True"))
{
connection.Open();
string sql = "SELECT          T_CLOCK_SCORE,T_LANGUAGE_SCORE,T_RECALL_SCORE,T_REGISTRATION_SCORE,T_ORIENTATION  _SCORE,T_TIME FROM TEST_RESULTS WHERE P_ID='" + pID + "' AND T_DATE='"+ tdate +"'";
 using(SqlCommand command = new SqlCommand(sql, connection))
{ 
command.CommandTimeout = 3600;             
using (SqlDataReader reader =     command.ExecuteReader(CommandBehavior.SequentialAccess))
    { 
while (reader.Read())
        {
              MessageBox.Show("hello4");
                String clockScoreString = reader["T_CLOCK_SCORE"].ToString();
                MessageBox.Show(clockScoreString);
                clockScore = Int32.Parse(clockScoreString);
                String langScoreString = reader["T_LANGUAGE_SCORE"].ToString();
                langScore = Int32.Parse(langScoreString);
                String recallScoreString = reader["T_RECALL_SCORE"].ToString();
                recallScore = Int32.Parse(recallScoreString);
                String regScoreString = reader["T_REGISTRATION_SCORE"].ToString();
                regScore = Int32.Parse(regScoreString);
                String orientScoreString = reader["T_ORIENTATION_SCORE"].ToString();
                orientScore = Int32.Parse(orientScoreString);
                String timeScoreString = reader["T_TIME"].ToString();
                timeScore = Int32.Parse(timeScoreString);
        }
        reader.Close(); 
    }
}  


this.TestResultBarChart.Series["Series1"].Points.AddXY("Clock Score", clockScore);
this.TestResultBarChart.Series["Series1"].Points.AddXY("Language Score",     langScore);
this.TestResultBarChart.Series["Series1"].Points.AddXY("Recall Score", recallScore);
this.TestResultBarChart.Series["Series1"].Points.AddXY("Registration Score", regScore);
this.TestResultBarChart.Series["Series1"].Points.AddXY("Orientation Score", orientScore);


}

        }

Here is a pic of the data: Test_results_table

here is a pic of the interface with the first record working: interface

I know this has something to do with the reader but can't work out how to get to function correctly

Any help is very much appreciated

You are reading in a loop all the returned values, then exit from the loop and use just the last value to set your Points. You should move the Point settings inside the loop

....
while (reader.Read())
{
    clockScore = Convert.ToInt32(reader["T_CLOCK_SCORE"]);
    langScore = Convert.ToInt32(reader["T_LANGUAGE_SCORE"]);
    recallScore = Convert.ToInt32(reader["T_RECALL_SCORE"]);
    regScore = Convert.ToInt32(reader["T_REGISTRATION_SCORE"]);
    orientScore = Convert.ToInt32(reader["T_ORIENTATION_SCORE"]);
    timeScore = Convert.ToInt32(reader["T_TIME"]);
    this.TestResultBarChart.Series["Series1"].Points.AddXY("Clock Score", clockScore);
    this.TestResultBarChart.Series["Series1"].Points.AddXY("Language Score",     langScore);
    this.TestResultBarChart.Series["Series1"].Points.AddXY("Recall Score", recallScore);
    this.TestResultBarChart.Series["Series1"].Points.AddXY("Registration Score", regScore);
    this.TestResultBarChart.Series["Series1"].Points.AddXY("Orientation Score", orientScore);            
}
reader.Close(); 

Note that your query is built using string concatenation. This is a well known problem with database code. Never do it and use a parameterized query

EDIT
Looking at your comment below, I repeat the advice to use a parameterized query instead of string concatenation. Not only this avoid Sql Injection hacks but also you don't leave the job to understand the meaning of your values to the database engine

DateTime tDate = Convert.ToDateTime(comboBox2.Text);
......
string sql = @"SELECT 
                   T_CLOCK_SCORE,T_LANGUAGE_SCORE,T_RECALL_SCORE,
                   T_REGISTRATION_SCORE,T_ORIENTATION_SCORE,T_TIME 
               FROM TEST_RESULTS 
               WHERE P_ID=@id AND T_DATE=@date";

using(SqlCommand command = new SqlCommand(sql, connection))
{ 
     command.Parameters.Add("@id", SqlDbType.Int).Value = pID;
     command.Parameters.Add("@date", SqlDbType.Date).Value = tdate;
     command.CommandTimeout = 3600;             
     using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess))
     { 
          while (reader.Read())
          ....

In this example I assume that the variable pID is of type integer and the variable tDate is of type DateTime matching the type of the database fields. This doesn't leave any doubt to the database engine on your values.
Of course if the fields are of different type then you should change the SqlDbType accordingly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM