I have this code. When I execute this once, I am able to get the correct list. But when I run this method again, the reader has no data. I was thinking did I forget to close some connection before calling it again, thus leading to the null result
public IEnumerable<List<string>> retreiveList()
{
string query = "SELECT * FROM table1;";
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataReader reader;
reader = cmd.ExecuteReader();
while (reader.Read())
{
List<string> toReturn=new List<string>();
for (int i = 0; i < reader.FieldCount; i++)
toReturn.Add(reader[i].ToString());
yield return toReturn;
}
reader.Close();
}
Related
I have this code
string query = "SELECT * FROM table;"
try
{
using (SqlConnection connection = new SqlConnection(this.ConnectionString))
{
connection.Open();
using (SqlCommand cmd = new SqlCommand(query, connection))
{
SqlDataReader reader = cmd.ExecuteReader();
}
connection.Close();
}
}
In reader I receive the number of rows in the table, but no data. Where am I getting lost?
Once you've called ExecuteReader you need to loop through it, reading each row:
while(reader.Read())
{
// Process the row...
}
Also, it's good practice to put the reader into a using block:
using(SqlDataReader reader = cmd.ExecuteReader())
{
while(reader.Read())
{
// Process the row
}
}
You need to read the reader
https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/retrieving-data-using-a-datareader#:~:text=To%20retrieve%20data%20using%20a,rows%20from%20a%20data%20source.
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
//
}
}
When filling a combobox with data in database, the first row in database was missing.
con = new SqlConnection(cs.connetionString);
con.Open();
Sql = "SELECT * FROM ItemRate";
command = new SqlCommand(Sql, con);
SqlDataReader reader = command.ExecuteReader();
reader.Read();
while (reader.Read())
{
string cat = reader["RateOfInt"].ToString();
comboBox4.Items.Add(cat);
}
Calling reader.Read() advances one row, so the first time you call it before the while loop it already lands on the first row, but then you call it again in the while condition, so it advances to the second row, just remove the call before the condition.
con = new SqlConnection(cs.connetionString);
con.Open();
Sql = "SELECT * FROM ItemRate";
command = new SqlCommand(Sql, con);
SqlDataReader reader = command.ExecuteReader();
// remove this line
// reader.Read();
while (reader.Read())
{
string cat = reader["RateOfInt"].ToString();
comboBox4.Items.Add(cat);
}
Edit: Here is the example from the Docs
con = new SqlConnection(cs.connetionString);
con.Open();
Sql = "SELECT * FROM ItemRate";
command = new SqlCommand(Sql, con);
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
string cat = reader["RateOfInt"].ToString();
comboBox4.Items.Add(cat);
}
Everything works fine except the labels[i]. The loop is always writing in htmlLabel1 and never in htmlLabel2 etc.
Why does the iteration doesn't work by labels[i] but at Reader.GetValue(i) just fine?
MySqlConnection connection = new MySqlConnection(myConnectionString);
MySqlCommand command = connection.CreateCommand();
command.CommandText = "SELECT number FROM numbers ORDER BY RAND() LIMIT 2; ";
MySqlDataReader Reader;
connection.Open();
Reader = command.ExecuteReader();
while (Reader.Read())
{
HtmlLabel[] labels = new HtmlLabel[] {
htmlLabel1,
htmlLabel2,
htmlLabel3
};
for (int i = 0; i < Reader.FieldCount; i++)
{
labels[i].Text = Reader.GetValue(i).ToString();
Console.WriteLine(Reader.GetValue(i).ToString());
}
}
connection.Close();
There is only one field so Reader.FieldCount will return 1 every time.
if you want to loop through rows use the following code
MySqlConnection connection = new MySqlConnection(myConnectionString);
MySqlCommand command = connection.CreateCommand();
command.CommandText = "SELECT number FROM numbers ORDER BY RAND() LIMIT 2; ";
MySqlDataReader Reader;
connection.Open();
Reader = command.ExecuteReader();
int i=0;
HtmlLabel[] labels = new HtmlLabel[] {
htmlLabel1,
htmlLabel2,
htmlLabel3
};
while (Reader.Read())
{
//for (int i = 0; i < Reader.FieldCount; i++)
//{
labels[i].Text = Reader[0].ToString();
Console.WriteLine(Reader[0].ToString());
//}
i +=1;
}
connection.Close();
This is what I want:
A method that is within a class that will return iteratively the values of a certain column. This values will the be added to a combobox when the method is invoked. Here is my attempt:
public string FillCombo()
{
string connstring = "Data Source=HP\\SQLEXPRESS;Initial Catalog=Arana;Integrated Security=True";
string query = "Select * from categorias";
SqlConnection conn = new SqlConnection(connstring);
SqlCommand command = new SqlCommand(query, conn);
SqlDataReader read;
conn.Open();
read = command.ExecuteReader();
while (read.Read())
{
string combodata = read.GetString(1);
return (combodata);
}
return null;
}
however, when this method is invoked, it only returns the first row into de combobox, not the other values.
It's called yield
http://msdn.microsoft.com/en-us/library/vstudio/9k7k7cf0.aspx
From the manual
public static System.Collections.IEnumerable Power(int number, int exponent)
{
int result = 1;
for (int i = 0; i < exponent; i++)
{
result = result * number;
yield return result;
}
}
yield will send a collection of return results from inside a loop after the loop has completed.
You can close data connections using a try/finally block around the loop.
public IEnumerable FillCombo()
{
SqlConnection conn = new SqlConnection(connstring);
SqlCommand command = new SqlCommand(query, conn);
SqlDataReader read;
conn.Open();
read = command.ExecuteReader();
try
{
while (read.Read())
{
yield return read.GetString(1);
}
}
finally
{
read.close();
conn.close();
}
}
A cool and often overlooked feature of C#
Consider using a List of string as an output. The following minor change to your code should help...
public List<string> FillCombo()
{
List<string> comboList = new List<string>();
string connstring = "Data Source=HP\\SQLEXPRESS;Initial Catalog=Arana;Integrated Security=True";
string query = "Select * from categorias";
SqlConnection conn = new SqlConnection(connstring);
SqlCommand command = new SqlCommand(query, conn);
SqlDataReader read;
conn.Open();
read = command.ExecuteReader();
while (read.Read())
{
string combodata = read.GetString(1);
comboList.Add(combodata);
}
return comboList;
}
Good Luck!
Why can't I call OpenConnection() twice in one method? When I call it this error appears:
The connection is already open.
I call it twice in SelectDisPatient() and Count(). See my code at for (int index = 0; index < Count(); index++)
This method SelectDisPatient:
public void SelectDisPatient(FrmVIRGO frm)
{
string query = "SELECT id_pasien FROM tb_patient_information ";
if (this.OpenConnection() == true)
{ //Create Command
MySqlCommand cmd = new MySqlCommand(query, connection);
//Create a data reader and Execute the command
MySqlDataReader dataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
if (dataReader.HasRows)
{
for (int index = 0; index < Count(); index++)
dataReader.Read();
frm.tbName.Text = dataReader[0].ToString();
}
//close Data Reader
dataReader.Close();
//close Connection
this.CloseConnection();
}
}
This Count() method:
public int Count()
{
string query = "SELECT Count(*) FROM tb_patient_information";
int Count = -1;
//Open Connection
if (this.OpenConnection() == true)
{
//Create Mysql Command
MySqlCommand cmd = new MySqlCommand(query, connection);
//ExecuteScalar will return one value
Count = int.Parse(cmd.ExecuteScalar()+"");
//close Connection
this.CloseConnection();
return Count;
}
else
{
return Count;
}
}
But when I remove (this.OpenConnection() == true) in the Count() method it says I need to close the connection.
Try:
public void SelectDisPatient(FrmVIRGO frm)
{
int count = Count();
string query = "SELECT id_pasien FROM tb_patient_information ";
if (this.OpenConnection() == true)
{ //Create Command
MySqlCommand cmd = new MySqlCommand(query, connection);
//Create a data reader and Execute the command
MySqlDataReader dataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
if (dataReader.HasRows)
{
for (int index = 0; index < count ; index++)
dataReader.Read();
frm.tbName.Text = dataReader[0].ToString();
}
//close Data Reader
dataReader.Close();
//close Connection
this.CloseConnection();
}
}