With one SELECT query, the code seems to add to the listbox correctly, but when I add another query, the listbox doesn't show anything anymore, and it seems that that rdr[3] does not exists (Contact has 3 columns and Numar_contact has one column (should't it be this one the rdr[3]?))
string connString = #"database=Agenda_db; Data Source=Marian-PC\SQLEXPRESS; Persist Security Info=false; Integrated Security=SSPI";
SqlConnection conn = new SqlConnection(connString);
try {
conn.Open();
SqlCommand cmd = new SqlCommand("SELECT * FROM Contact;"+ "SELECT * FROM Numar_contact", conn)
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
listBox1.Items.Add(rdr[0].ToString() + ' ' + rdr[1].ToString() + ' ' + rdr[2].ToString()+' '+ rdr[3].ToString());
}
rdr.Close();
Join your queries with a UNION. The way you've got it now, it'll return two results sets.
SELECT [col1], [col2] FROM Contact
UNION ALL
SELECT [col1], [col2] FROM Numar_contact
As DJ KRAZE pointed out in a comment, it might not be a bad idea to wrap this in a sproc or a TVF. But this will work too.
Edit:
I just learned via comments that the two tables are actually unrelated. In light of that, I'd be tempted to use two SqlCommands with two, distinct foreach loops. But if you're sold on this way,
SELECT id_contact, nume_contact, prenume_contact FROM Contact
UNION ALL
SELECT id_contact, numar, NULL FROM Numar_contact
This will align the data from the two tables, but where the second table doesn't have a [prenume_contact] it will select NULL. I might have mixed up the column positions here, since I don't really understand what those names are meant to represent.
Edit 2:
string connString = #"database=Agenda_db; Data Source=Marian-PC\SQLEXPRESS; Persist Security Info=false; Integrated Security=SSPI";
using (SqlConnection conn = new SqlConnection(connString))
{
try
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("SELECT * FROM Contact", conn))
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
listBox1.Items.Add(rdr[0].ToString() + " " + rdr[1].ToString() + " " + rdr[2].ToString());
}
}
using (SqlCommand cmd2 = new SqlCommand("SELECT * FROM Numar_contact", conn))
using (SqlDataReader rdr2 = cmd.ExecuteReader())
{
while (rdr2.Read())
{
listBox1.Items.Add(rdr2[0].ToString() + " " + rdr2[1].ToString());
}
}
}
catch { }
}
Edit 3, thanks to insight from Scott Chamberlain:
On the other hand, you might want to perform a JOIN of some kind, most commonly an INNER JOIN. Note that this is an entirely different operation from any we've talked about before.
SELECT Contact.id_contact, Contact.nume_contact, Contact.prenume_contact, Numar_contact.numar
FROM Contact
INNER JOIN Numar_contact on Contact.id_contact = Numar_contact.id_contact
This will tie the two tables together, returning a record for each contact-numar_contact. Again, this is definitely not the same as doing a UNION. Make sure you're aware of the difference before you pick which you want.
Use this if your second table contains data that relates many-to-one to the first table.
Thanks to your comment, what you are wanting to do is JOIN the tables.
SELECT Contact.id_contact, nume_contact, prenume_contact, numar
FROM Contact
INNER JOIN Numar_contact on Contact.id_contact = Numar_contact.id_contact
That will combine the two tables in to four columns where id_contact matches in both tables.
You may want a INNER JOIN or a LEFT JOIN depending on if you want rows to show up only when there is a item in the 2nd table or show up anyway and just make the 4th column DBNull.Value.
Yes you can.
Here is an example from the MSDN I've modified to use your code - you need to move the reader to the Next ResultSet
string connString = #"database=Agenda_db; Data Source=Marian-PC\SQLEXPRESS; Persist Security Info=false; Integrated Security=SSPI";
SqlConnection conn = new SqlConnection(connString);
SqlCommand myCommand = new SqlCommand("SELECT * FROM Contact; SELECT * FROM Numar_contact", conn);
SqlDataReader myReader ;
int RecordCount=0;
try
{
myConnection.Open();
myReader = myCommand.ExecuteReader();
while (myReader.Read())
{
//Write logic to process data for the first result.
RecordCount = RecordCount + 1;
}
MessageBox.Show("Total number of Contacts: " + RecordCount.ToString());
bool moreResults = myReader.NextResult(); // <<<<<<<<<<< MOVE TO NEXT RESULTSET
RecordCount = 0;
while (moreResults && myReader.Read())
{
//Write logic to process data for the second result.
RecordCount = RecordCount + 1;
}
MessageBox.Show("Total number from Numar_contacts: " + RecordCount.ToString());
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
conn.Close(); // Could be replaced with using statement too
}
Related
Below is my code to connect to the database using MySqlDataReader. Now the if statement is working fine but the else statement doesnt. When i use the debug function in VS it kept skipping the else statement and jump to the reader.Close();.
Any idea. Thanks
private void db()
{
string constr = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
MySqlConnection connection = new MySqlConnection(constr);
connection.Open();
MySqlCommand command = connection.CreateCommand();
command.CommandText = "SELECT * FROM user Where user_id ='" + Userid.Text + "'" + "And password='" + Password.Text + "'";
MySqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
if (!reader.IsDBNull(0))
{
Label1.Text = reader["user_id"].ToString();
}
else
{
Label1.Text = "nodata";
}
reader.Close();
}
}
First of all: Don't use string concatenation for building queries, but use parameterized queries!
As for your problem: I assume this query will only return either 1 or 0 rows, so you don't need the loop but just check
if (reader.Read()) {
//...
}
Using SELECT * with column indexes is potentially dangerous, because you may not know what the "first" column returned is. I would suggest name your desired columns in the query
SELECT user_id, user_name ... FROM ...
What is the value of the first column returned? I assume, it's the user_id. Thus, this can never fulfill the condition IsDBNull(0) because user_id is your matching criterion in the WHERE clause. If your WHERE clause does not match any record in the table, reader.Read() will already fail, so you'll never get to your else branch.
Furthermore, I would suggest a using clause, which will dispose the reader automatically, so you don't have to care about closing it.
command.CommandText = "SELECT user_id, foo, bar from user where user_id = #userid and password = #password";
command.Parameters.AddWithValue("#user_id", UserId.Text);
command.Parameters.AddWithValue("#password", Passowrd.Text);
using (MySqlDataReader reader = command.ExecuteReader()) {
if (reader.Read()) {
Label1.Text = reader["user_id"].ToString();
} else {
Label1.Text ="nodata";
}
}
enter image description hereI'm trying to show all my items on a combobox, but when y run my app I only get one item. Can you help me please, here's my code
try
{
MySqlConnection conection = new MySqlConnection("server = 127.0.0.1; database = sistemalaboratorio; Uid = root; pwd =;");
string selectQuery = "SELECT clavemateria FROM materia";
conection.Open();
MySqlCommand command = new MySqlCommand(selectQuery, conection);
MySqlDataReader reader = command.ExecuteReader();
while (reader.Read());
{
comboBox1.Items.Add(reader["clavemateria"].ToString());
}
} catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
Assuming this read is happening before the page loads the combobox, make sure your materia table has more than 1 record in it.
These queries might usful to count the records in your SQL table in case you dont have direct access using SQL Management studio
SELECT COUNT(*) FROM materia WITH (NOLOCK)
-- NOLOCK here is for testing for this answer: no more, no less
or
SELECT clavemateria, count(*)
FROM materia
GROUP BY clavemateria
Also you can try this:
string qr1 = "select * from materia ";
SqlCommand cmd1 = new SqlCommand(qr1, con);
con.Open();
SqlDataReader dr1 = cmd1.ExecuteReader();
cmbcat.Items.Clear();
while (dr1.Read())
{
cmbcat.Items.Add(new Item(dr1["clavemateria"].ToString(), dr1["clavemateria"].ToString()));
}
con.Close();
Or refer to this example
I need to read data from a SQL Server database. Something doesn't work with syntax of the table, which has Id as a primary key plus several items.
SqlConnection CON = new SqlConnection("Data Source = pc\\sqlexpress; Initial Catalog = dccDB; Integrated Security = True");
string strSQL = "SELECT Id Item" + "FROM [dbo.Table]";
SqlCommand cmd = new SqlCommand(strSQL, CON);
{
CON.Open();
MessageBox.Show("SQL DataBase dccDB.dbo is connected");
SqlDataReader reader = cmd.ExecuteReader(); (ERROR !!!)
while ( reader.Read() )
{
MessageBox.Show( reader["Id"].ToString(), reader["Item"].ToString());
}
reader.Close();
CON.Close();
}
There is a error message: ex.Message
Wrong syntax close to 'dbo.Table'.
Many thanks for your ideas.
You're missing a space in your SQL and using the brackets incorrectly. Columns need to be separated by commas. The line should be:
string strSQL = "SELECT Id, Item FROM [dbo].[Table]";
Have a space after Item in ur query, and separate dbo.table to [dbo].[table] like:
string strSQL = "SELECT Id, Item " + "FROM [dbo].[Table]";
There is no space between Item and From, replace your strSql line with following:
string strSQL = "SELECT Id Item " + "FROM [dbo.Table]";
i m trying to retrieve the Specialization ID from a table called Specializationtbl, using C# MSVS 2008 and the table includes SpecializationName and SpecializationID beside some other rows and my question is related to some error " No Data to present ", the command goes as bellow:
SqlCommand READSpecID = new SqlCommand("SELECT * FROM Specializationtbl WHERE SpecializationName='" + comboBox1.Text + "'" , DBcnction);
DBcnction.Open();
SqlDataReader ReadSpecID_ = READSpecID.ExecuteReader();
ReadSpecID_.Read();
int SpecID_ = Convert.ToInt16(ReadSpecID_["SpecID"].ToString());
DBcnction.Close();
i also tried to Select the "SpecID" instead of all the rows, but cant seem to seal the query correctly and keep receiving "No data present " error, any idea where am i making the mistake?
1) Try opening DBcnction before assigning the value to READSPecID
DBcnction.Open();
SqlCommand READSpecID = new SqlCommand("SELECT * FROM Specializationtbl WHERE SpecializationName='" + comboBox1.Text + "'" , DBcnction);
2) Run the command in SSMS:
SELECT * FROM Specializationtbl WHERE SpecializationName ='yourvalue'
and see if any results are returned
3) Check comboBox1.Text has a value in it
4) Validate the contents of comboBox1.Text (Or use paremetrised queries or a stored procedure) to ensure you do not become a victim of SQL Injection: http://en.wikipedia.org/wiki/SQL_injection
Refactor to solve your TWO problems:
Your SQL injection problem when building your SQL statement.
Use ExecuteScalar if you only need one value.
Implement using blocks.
string retVal;
using (var conn = new SqlConnection(SomeConnectionString))
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "SELECT SpecID FROM Specializationtbl WHERE SpecializationName= #Name";
cmd.Parameters.AddWithValue("#Name", comboBox1.Text);
conn.Open();
retVal = cmd.ExecuteScalar().ToString();
}
int specID = int.Parse(retVal);
If you really needed more than one value from your statement:
using (var conn = new SqlConnection(SomeConnectionString))
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "SELECT SpecID, Value2 FROM Specializationtbl WHERE SpecializationName= #Name";
cmd.Parameters.AddWithValue("#Name", comboBox1.Text);
conn.Open();
var dr = cmd.ExecuteReader();
while (dr.Read())
{
Customer c = new Customer {
ID = dr["SpecID"].ToString(),
Value = dr["Value2"].ToString(),
};
}
}
Need to first test if there are any rows. I suspect the query is returning zero rows.
if (ReadSpecID_.HasRows)
{
ReadSpecID_.Read();
}
My code:
SqlConnection con = new SqlConnection(WebConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString);
SqlCommand cmd = new SqlCommand();
//..........
cmd.CommandText = "SELECT * FROM TempQn WHERE creatorId= '" +
Session["administratorID"].ToString() + "'";
dr = cmd.ExecuteReader();
while (dr.Read())
{
int ids = Int32.Parse(dr["QuestionID"].ToString());
cmd.CommandText = " INSERT INTO Answers (QuestionId,Answer) Select c.QnId, c.Answer From TempAns c Where c.Id = " + ids + " ";
cmd.ExecuteNonQuery(); //this line
}
dr.Close();
The error is:
There is already an open DataReader associated with this Command which must be closed first.
What kind of command should replace the cmd.ExecuteNonQuery();?
You can't execute any further SQL statements as long as the DataReader is "active".
To overcome this, store list of the SQL statements then exeucute them after reading:
cmd.CommandText = "SELECT * FROM Question WHERE SurveyID= '" + sID + "'";
dr = cmd.ExecuteReader();
List<string> arrSQL = new List<string>();
while (dr.Read())
{
int ids = Int32.Parse(dr["QuestionID"].ToString());
arrSQL.Add("INSERT INTO Answers (QuestionId,Answer) Select c.QnId, c.Answer From TempAns c Where c.Id = " + ids + " ");
}
dr.Close();
arrSQL.ForEach(strSQL =>
{
cmd.CommandText = strSQL;
cmd.ExecuteNonQuery();
});
Your current code is vulnerable to SQL injection attacks though and isn't good practice - you better use Parameter instead of injecting value to the raw SQL - here is how to achieve that:
cmd.CommandText = "SELECT * FROM Question WHERE SurveyID=#id";
cmd.Parameters.AddWithValue("#id", sID);
dr = cmd.ExecuteReader();
List<int> arrQuestions = new List<int>();
while (dr.Read())
{
int ids = Int32.Parse(dr["QuestionID"].ToString());
arrQuestions.Add(ids);
}
dr.Close();
cmd.CommandText = "INSERT INTO Answers (QuestionId, Answer) Select c.QnId, c.Answer From TempAns c Where c.Id = #id";
arrQuestions.ForEach(id =>
{
cmd.Parameters["#id"].Value = id;
cmd.ExecuteNonQuery();
});
You already have one command associated with "cmd".
dr = cmd.ExecuteReader();
while (dr.Read())
{
int ids = Int32.Parse(dr["QuestionID"].ToString());
SqlCommand sqlCmd = new SqlCommand("INSERT INTO Answers (QuestionId,Answer) Select c.QnId, c.Answer From TempAns c Where c.Id = " + ids + " ");
sqlCmd.ExecuteNonQuery(); //this line
}
dr.Close();
So Like ive given above create a new command for the insertion.
This single query should do the job (not sure of you exact data model, adapt if required ):
INSERT INTO Answers (QuestionId,Answer)
Select c.QnId, c.Answer
From TempAns c
inner join Question q on c.QnId = q.Id
where q.SurveyID = #SurveyID
In order to avoid SQl Injection, use this C# code :
cmd.CommandTest = #"INSERT INTO Answers (QuestionId,Answer)
Select c.QnId, c.Answer
From TempAns c
inner join Question q on c.QnId = q.Id
where q.SurveyID = #SurveyID";
SqlParameter param = cmd.Parameters.Add("#SurveyID", SqlDbType.Int);
param.Value = yourSurveyId;
cmd.Open(); // it would be better to check the status before
cmd.ExecuteNonQuery();
cmd.Close();
Instead of using a 2nd connection object, you could change your connection string and use MARS (Multiple active result set) for this purpose. Add the following statement to your connection string:
MultipleActiveResultSets=True
EDIT:
And like the other's said, use SqlParameters for your parameters and not string concatenation. It's not only a security issue, but also a huge performance hit!
you need to declare a new command object because cmd is already being used for reading the data when you are trying to use it for insert statement. Also, don't use string concatenation from sql command, its a bad practice and vulnerable to SQL injection. using parameters.