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.