This is a really noob-problem but im tearing my hair soon.
I'm trying to read from my local database but it gives me nothing.
Here is the code:
protected void readBtn2_Click(object sender, EventArgs e)
{
string ConnString = "server=localhost; Trusted_Connection=yes; database=expreimentalDB";
string SqlString = ("SELECT * FROM tblCity WHERE city = '#city'");
using (SqlConnection conn = new SqlConnection(ConnString))
{
using (SqlCommand cmd = new SqlCommand(SqlString, conn))
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("city", cityTB.Text);
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
GridView1.DataSource = reader;
GridView1.DataBind();
}
}
}
}
The connectionstring should work (because if i rename the database part in the string it crashes).
The sql is working (tried it in sql manager)
reader (the SqlDataReader) is empty
What is it I havnt tried out yet?
You need to remove the single quotes from around #city in your query so that it becomes
string SqlString = "SELECT * FROM tblCity WHERE city = #city";
and then
cmd.Parameters.AddWithValue("city", cityTB.Text);
needs to be changed to
cmd.Parameters.AddWithValue("#city", cityTB.Text);
I'm not quite sure, but shouldn't you have to prefix the name of the parameter with the #-sign when adding it to your command? Like this:
cmd.Parameters.AddWithValue("#city", cityTB.Text);
Related
I can't extract the values through a query and insert them into textboxes
Where am I going wrong?
Request.QueryString.Get("ID_Persona");
string query = "SELECT ID,Nome,Cognome,Email,CodiceFiscale FROM Persona WHERE ID = #id";
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["dbConnection"].ConnectionString))
{
SqlCommand cmd = new SqlCommand(query, con);
cmd.Parameters.AddWithValue("#ID","");
cmd.Parameters.AddWithValue("#Nome", TextBox1.Text);
cmd.Parameters.AddWithValue("#Cognome", TextBox15.Text);
cmd.Parameters.AddWithValue("#Email", TextBox20.Text);
cmd.Parameters.AddWithValue("#CodiceFiscale", TextBox22.Text);
con.Open();
cmd.ExecuteNonQuery();
}
You need to use ExecuteReader to read values, something like this:
var connectionString = ConfigurationManager.ConnectionStrings["dbConnection"].ConnectionString;
string query = "SELECT ID,Nome,Cognome,Email,CodiceFiscale FROM Persona WHERE ID = #id";
using (SqlConnection con = new SqlConnection(connectionString))
{
using (var cmd = new SqlCommand(query, con))
{
cmd.Parameters.AddWithValue("#ID", Request.QueryString.Get("ID_Persona"));
con.Open();
using (var rdr = cmd.ExecuteReader())
{
if (rdr.Read())
{
//IDTextBox? = rdr["Id"].ToString(),
TextBox1.Text = rdr["Nome"].ToString(),
TextBox15.Text = rdr["Cognome"].ToString(),
TextBox20.Text= rdr["Email"].ToString(),
TextBox22.Text= rdr["CodiceFiscale"].ToString(),
}
}
}
}
You should use a ExecuteReader() instead of ExecuteNonQuery() since ExecuteNonQuery is meant for DML operations. Again, you need only the ID value to be passed then why you are passing unnecessary parameters to your query. Remove them all. An example below
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
Console.WriteLine(String.Format("{0}", reader["Email"]));
}
I can see several issues:
You should use ExecuteReader() instead of ExecuteNonQuery()
You should provide just 1 parameter - #ID; I doubt if it should have an empty value.
You should wrap IDisposable into using
Code:
string query =
#"SELECT ID,
Nome,
Cognome,
Email,
CodiceFiscale
FROM Persona
WHERE ID = #id";
using (SqlConnection con = new SqlConnection(...))
{
con.Open();
using SqlCommand cmd = new SqlCommand(query, con)
{
// I doubt if you want empty Id here.
// I've assumed you want to pass ID_Persona
cmd.Parameters.AddWithValue("#ID", Request.QueryString.Get("ID_Persona"));
using (var reader = cmd.ExecuteReader())
{
if (reader.Read())
{
TextBox1.Text = Convert.ToString(reader["Nome"]);
TextBox15.Text = Convert.ToString(reader["Cognome"]);
TextBox20.Text = Convert.ToString(reader["Email"]);
TextBox22.Text = Convert.ToString(reader["CodiceFiscale"]);
}
}
}
}
This question already has answers here:
What are good ways to prevent SQL injection? [duplicate]
(4 answers)
Closed 4 years ago.
I have been doing simple website using ASP, but am not sure how to add parameterised query to avoid any SQL Injection attacks, can anybody help me to do it i always encounter errors and it has been more than a week that am doing and still i can't figured out. below i attached my simple code.
protected void btnLogin_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
string sql = "Select * From Users Where UserID='" + txtUser.Text + "' And Password='" + txtPwd.Text + "'";
con.Open();//opens the connection
//create the command object
cmd = new SqlCommand(sql, con);
//assigns the result to the reader
dr = cmd.ExecuteReader();
dr.Read();//read the record's data
//if there's a matching record found
if (dr.HasRows)
{
if (dr["UserType"].Equals("admin"))
{
Response.Redirect("dhome.aspx");
}
else if (dr["UserType"].Equals("staff"))
{
Response.Redirect("shome.aspx");
}
else if (dr["UserType"].Equals("member"))
{
Response.Redirect("mhome.aspx");
}
}
else
{
lblAlert.Text = "Invalid username or password!";
}
dr.Close(); //close the data reader
con.Close();//close the connection //declaration of data access components
}
You should add them using SqlCommand.Parameters.Add():
using (SqlConnection con = new SqlConnection(ConnectionString))
{
SqlCommand cmd = new SqlCommand("Select * From Users Where UserID=#username And Password=#password", con);
cmd.Parameters.Add("#username", SqlDbType.VarChar).Value = username;
cmd.Parameters.Add("#password", SqlDbType.VarChar).Value = password;
//rest of the code ...
}
You need to use SqlCommand.Parameters.Add. You should also implement dispose (via using blocks or calling Dispose) to release resources after use:
string connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
string sql = "Select * From Users Where UserID=#user And Password=#pwd";
using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(sql, connection))
{
command.Parameters.Add("#user", SqlDbType.VarChar);
command.Parameters["#user"].Value = "value";
command.Parameters.Add("#pwd", SqlDbType.VarChar);
command.Parameters["#pwd"].Value = "value";
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
if (reader.HasRows)
{
// read row
}
}
}
Am trying to populate a listbox with values generated by a query, the code runs without any problems but the listbox is not displaying any results, what am i doing wrong, is there anything missing??
String sql = "SELECT * FROM products where code = "+textBox1.Text;
SqlDataAdapter dataAdapter = new SqlDataAdapter(sql, conn); //c.con is the connection string
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.Read())
{
listBox1.Items.Add(reader["description"].ToString() + ": "+reader["price"].ToString());
listBox1.Refresh();
}
reader.Close();
conn.Close();
}
}
If your code column is of string type then
String sql = "SELECT * FROM products where code = '"+textBox1.Text + "'";
SqlDataAdapter dataAdapter = new SqlDataAdapter(sql, conn); //c.con is the connection string
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while(reader.Read())
{
listBox1.Items.Add(reader["description"].ToString() + ": "+reader["price"].ToString());
}
reader.Close();
}
conn.Close();
}
Also to add all values, use while instead of if to traverse all the records in the reader. And also close the connection after the using statement.
I am sure the wrong sequence is causing the issue.
I'm making some assumptions here about your code, is 'code' a number? If not, did you try:
String sql = "SELECT * FROM products where code = '"+textBox1.Text+"'";
?
I have question about using why i can not use the same instance of SQLCommand more than one time in the same code?
I tried the code down here and it runs good for the gridview but when i changed the query by using cmd.CommandText() method it keeps saying:
There is already an open DataReader associated with this Command which must be closed first.
This is the code:
string cs = ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString;
SqlConnection con = new SqlConnection(cs);
try
{
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
con.Open();
cmd.CommandText = "Select top 10 FirstName, LastName, Address, City, State from Customers";
GridView1.DataSource = cmd.ExecuteReader();
GridView1.DataBind();
cmd.CommandText = "SELECT TOP 10 COUNT(CreditLimit) FROM Customers";
int total = (int)cmd.ExecuteScalar();
TotalCreditLble.Text = "The total Credit :" + total.ToString();
}
catch(Exception exp)
{
Response.Write(exp.Message);
}
finally
{
con.Close();
}
The problem is that you are using the SqlCommand object to generate a DataReader via the command.ExecuteReader() command. While that is open, you can't re-use the command.
This should work:
using (var reader = cmd.ExecuteReader())
{
GridView1.DataSource = reader;
GridView1.DataBind();
}
//now the DataReader is closed/disposed and can re-use command
cmd.CommandText = "SELECT TOP 10 COUNT(CreditLimit) FROM Customers";
int total = (int)cmd.ExecuteScalar();
TotalCreditLble.Text = "The total Credit :" + total.ToString();
There is already an open DataReader associated with this Command which must be closed first.
This is the very reason you don't share a command. Somewhere in your code you did this:
cmd.ExecuteReader();
but you didn't leverage the using statement around the command because you wanted to share it. You can't do that. See, ExecuteReader leaves a connection to the server open while you read one row at a time; however that command is locked now because it's stateful at this point. The proper approach, always, is this:
using (SqlConnection c = new SqlConnection(cString))
{
using (SqlCommand cmd = new SqlCommand(sql, c))
{
// inside of here you can use ExecuteReader
using (SqlDataReader rdr = cmd.ExecuteReader())
{
// use the reader
}
}
}
These are unmanaged resources and need to be handled with care. That's why wrapping them with the using is imperative.
Do not share these objects. Build them, open them, use them, and dispose them.
By leveraging the using you will never have to worry about getting these objects closed and disposed.
Your code, written a little differently:
var cs = ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString;
var gridSql = "Select top 10 FirstName, LastName, Address, City, State from Customers";
var cntSql = "SELECT TOP 10 COUNT(CreditLimit) FROM Customers";
using (SqlConnection con = new SqlConnection(cs))
{
con.Open();
try
{
using (SqlCommand cmd = new SqlCommand(gridSql, con))
{
GridView1.DataSource = cmd.ExecuteReader();
GridView1.DataBind();
}
using (SqlCommand cmd = new SqlCommand(cntSql, con))
{
int total = (int)cmd.ExecuteScalar();
TotalCreditLble.Text = "The total Credit :" + total.ToString();
}
}
catch(Exception exp)
{
Response.Write(exp.Message);
}
}
Thank u quys but for the guys who where talking about using block !
why this code work fine which i seen it on example on a video ! It's the same thing using the same instance of SqlCommand and passing diffrent queries by using the method CommanText with the same instance of SqlCommand and it's execute just fine , this is the code :
using (SqlConnection con = new SqlConnection(cs))
{
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
con.Open();
cmd.CommandText = "Delete from tbleProduct where ProductID= 4";
int TotalRowsAffected = cmd.ExecuteNonQuery();
Response.Write("Total rows affected :" + TotalRowsAffected );
cmd.CommandText = "Insert into tbleProduct values (4, 'Calculator', 100, 230)";
TotalRowsAffected = cmd.ExecuteNonQuery();
Response.Write("Total rows affected :" + TotalRowsAffected );
cmd.CommandText = "ypdate tbleProduct set QtyAvailbe = 234 where ProductID = 2";
TotalRowsAffected = cmd.ExecuteNonQuery();
Response.Write("Total rows affected :" + TotalRowsAffected );
}
protected void populateDataGrid()
{
string connectionString = configurationManager.ConnectionStrings["myConnectionString"].ConnectionString;
string command = "select * from student";
SqlDataAdapter dataAdapter = new SqlDataAdapter(command, connectionString);
DataSet data = new DataSet();
dataAdapter.Fill(data);
GridView1.DataSource = data;
GridView1.DataBind();
}
protected void Button2_Click(object sender, EventArgs e)
{
string connectionString = ConfigurationManager.ConnectionStrings["sqlstudentConnectionString"].ConnectionString;
string command = #"INSERT INTO [student] (studentID, studentFirstName, studentLastName)
VALUES (" + TextID.Text + ", '" + TextFirstName.Text + "', '" + TextLastName.Text + "')";
SqlConnection sqlConnection = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand();
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = command;
cmd.Connection = sqlConnection;
sqlConnection.Open();
cmd.ExecuteNonQuery();
sqlConnection.Close();
TextID.Text = "";
TextFirstName.Text = "";
TextLastName.Text = "";
populateDataGrid();
}
The first function gets all the table data and dumps it to a gridview.
The second function takes input and inserts it into the database.
How can these functions be condensed or simplified?
How can these functions be condensed or simplified?
I would focus on correctness before simplification. Currently I can see at least two problems with the code:
You should absolutely use parameterized SQL instead of putting the values into the SQL itself. Your current code is prone to SQL injection attacks.
You should use using statements so that connection and command are both closed automatically even if exceptions are thrown.
Then in terms of simplification:
You can use the SqlCommand constructor which takes the text and connection - the type defaults to Text anyway.
I would personally try to separate the UI code from the storage code, at least for a non-trivial project. You should look at ASP.NET MVC, at least to get some idea of separation, even if you don't change to start using it.
In Button2_Click(object sender, EventArgs e) method , you need to use parametrized query to avoid SQL Injection.
That is the standard way.
protected void Button2_Click(object sender, EventArgs e)
{
string connectionString = ConfigurationManager.ConnectionStrings["sqlstudentConnectionString"].ConnectionString;
string command = #"INSERT INTO [student] (
studentID, studentFirstName, studentLastName
) VALUES (
#studID, #FName, #LName
)";
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = command;
cmd.Parameters.AddWithValue("#studID", TextID.Text);
cmd.Parameters.AddWithValue("#FName", TextFirstName.Text);
cmd.Parameters.AddWithValue("#LName", TextLastName.Text);
cmd.Connection = sqlConnection;
sqlConnection.Open();
cmd.ExecuteNonQuery();
sqlConnection.Close();
}
TextID.Text = "";
TextFirstName.Text = "";
TextLastName.Text = "";
populateDataGrid();
}
Hope Its Helpful.