In my code neither of these queries appear to be running. The debug label is printing as "end" so it is executing something inside that code block, just appears it doesn't like the queries?
// Check input is all valid
if (Page.IsValid)
{
debug.Text = "begin";
using (SqlConnection cn = new SqlConnection(
ConfigurationManager.ConnectionStrings["LocalSqlServer"].ToString()))
{
// Verify that username is unique
using (SqlCommand cmd = new SqlCommand(
"UPDATE tblSiteSettings SET isActive = 0", cn))
{
cn.Open();
cn.Close();
}
using (SqlCommand cmd = new SqlCommand(
"INSERT INTO tblSiteSettings (allowProductRatings, allowComments, " +
"siteName, settingDate, isActive) VALUES (#allowRatings, " +
"#allowcomments, #siteName, getDate(), 1)", cn))
{
cmd.Parameters.Add("#allowRatings", SqlDbType.Bit).Value = 1;
cmd.Parameters.Add("#allowcomments", SqlDbType.Bit).Value = 1;
cmd.Parameters.Add("#siteName", SqlDbType.VarChar, 128).Value = "lol";
cn.Open();
cn.Close();
}
debug.Text = "end";
}
}
A few questions:
Why are they not executing?
In classic ASP for inserts, updates and deletes I would use con.Execute(query) as supposed to using a recordset, am I running my update statement correctly here?
Is my design of the queries good, or should I be executing them in a different manner?
The reason it's not doing anything is because you're not actually executing the queries. What you need to do is:
// Verify that username is unique
using (SqlCommand cmd = new SqlCommand("UPDATE tblSiteSettings SET isActive = 0", cn))
{
cn.Open();
cmd.ExecuteNonQuery();
cn.Close();
}
using (SqlCommand cmd = new SqlCommand("INSERT INTO tblSiteSettings (allowProductRatings, allowComments, siteName, settingDate, isActive) VALUES (#allowRatings, #allowcomments, #siteName, getDate(), 1)", cn))
{
cmd.Parameters.Add("#allowRatings", SqlDbType.Bit).Value = 1;
cmd.Parameters.Add("#allowcomments", SqlDbType.Bit).Value = 1;
cmd.Parameters.Add("#siteName", SqlDbType.VarChar, 128).Value = "lol";
cn.Open();
cmd.ExecuteNonQuery();
cn.Close();
}
It's the line cmd.ExecuteNoneQuery(); that you're missing. There are various different Execute methods exposed by the SqlCommand class, the most commonly used are:
ExecuteNonQuery: Executes a query and returns no result from the query (it does return the rows affected as its return value however)
ExecuteScalar: Executes a query and returns the value in the first column of the first row
ExecuteReader: Executes a query and returns the data to a SqlDataReader
Your are missing
cmd.ExecuteScalar();
You may also reuse you SqlConnection, you can open the connection right after the using (SqlConnection cn = new Sql... statement. You don't have to close the connection when the SqlConnection is in a using block, accordning to the documentation the connection is closed when you are leaving the using block.
Related
How come I'm getting this error while trying to update my database?
ExecuteNonQuery requires an open and available Connection. The connection's current state is closed
Here is the code:
cmd1 = new SqlCommand("UPDATE [guitarBrands] SET type = #type, name = #name, image = #image WHERE id = #id", con1);
con1.Open();
cmd1.Parameters.Add(new SqlParameter("type", newType.Text));
cmd1.Parameters.Add(new SqlParameter("name", newName.Text));
cmd1.Parameters.Add(new SqlParameter("image", newImage.Text));
cmd1.Parameters.Add(new SqlParameter("id", id));
cmd1.ExecuteNonQuery();
con1.Close();
cmd1.Parameters.Clear();
cmd = new SqlCommand("UPDATE [guitarItems] SET brand = #brand WHERE id = #id", con1);
con.Open();
cmd.Parameters.Add(new SqlParameter("brand", newName.Text));
cmd.Parameters.Add(new SqlParameter("id", id));
cmd.ExecuteNonQuery();
con.Close();
cmd.Parameters.Clear();
To avoid these sort of issues, it is recommended you utilize the tower of power.
using(var connection = new SqlConnection(dbConnection))
{
connection.Open();
using(var command = new SqlCommand(query, connection)
{
}
using(var command = new SqlCommand(query, connection)
{
}
}
So the beauty of the tower of power, the using block will implement via within the given code block. So this will make it clear, that both these commands are utilizing the same connection from the using. Also, once the code is out of scope it will implement the IDispose, which will call the garbage collector to free up your resources.
Also, should you choose. The SqlCommand, accepts a parameter array. So if you utilize a method call, you could simply do:
public static GetExample(string query, params SqlParameter[] parameters)
{
using(var connection = new SqlConnection("YourDbConnection"))
using(var command = new SqlCommand("YourQuery", connection))
{
connection.Open();
if(parameters != null)
if(parameters.Any())
command.Parameters.Add(parameters);
command.ExecuteNonQuery();
}
}
I can't recall if the collection is a add, add range, or concat. But either way the option exist.
cmd = new SqlCommand("UPDATE [guitarItems] SET brand = #brand WHERE id = #id", con1);
replace this line to this
cmd = new SqlCommand("UPDATE [guitarItems] SET brand = #brand WHERE id = #id", con);
In your code you use Connexion "con1" in both Commands "cmd1" and "cmd". It is OK to use just one connexion for both commands but then you should leave the connexion open until both command are executed.
In your case you choose to use a new connexion "con" for the second command but you reopen "con1".
So you get an error because "con" is never opened.
I'm trying to update an Access database through my C# web application but I'm currently facing a problem in WHERE statement not updating the records and not returning any errors.
I'm trying update a text field and the condition in my WHERE statement is an integer.
OleDbCommand cmd = new OleDbCommand("UPDATE Data SET Title = #Title WHERE ID = #ID");
cmd.CommandType = CommandType.Text;
cmd.Connection = conn;
cmd.Parameters.AddWithValue("#Title", TextBox1.Text);
cmd.Parameters.AddWithValue("#ID", param2);
I even tried doing it this way
OleDbCommand cmd = new OleDbCommand("UPDATE Data SET Title = ? WHERE ID = ?");
cmd.CommandType = CommandType.Text;
cmd.Connection = conn;
cmd.Parameters.AddWithValue("?", TextBox1.Text);
cmd.Parameters.AddWithValue("?", param2);
But it's still not updating!
What I found out trying to fix it is that when i replace the first parameter with a string between single quotes (see below), it actually updates the table.
OleDbCommand cmd = new OleDbCommand("UPDATE Data SET Title = 'test' WHERE ID = #ID");
Does any of you guys have an idea why is this happening?
Edit: This is the full code
using (OleDbConnection conn = new OleDbConnection(connectionString))
{
OleDbCommand cmd = new OleDbCommand("UPDATE Data SET Title = #Title WHERE ID = #ID");
cmd.CommandType = CommandType.Text;
cmd.Connection = conn;
cmd.Parameters.AddWithValue("#Title", TextBox1.Text);
cmd.Parameters.AddWithValue("#ID", param2);
conn.Open();
try
{
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
Edit 2:
This is my code after trying to set the data types, it's still not working.
To clarify, in my Access database ID is "AutoNumber" and Title is "Long Text"
using (OleDbConnection conn = new OleDbConnection(connectionString))
{
OleDbCommand cmd = new OleDbCommand("UPDATE Data SET Title = ? WHERE ID = ?");
cmd.CommandType = CommandType.Text;
cmd.Connection = conn;
cmd.Parameters.AddWithValue("Title", TextBox1.Text).OleDbType = OleDbType.VarChar;
cmd.Parameters.AddWithValue("ID", param2).OleDbType = OleDbType.Integer;
conn.Open();
try
{
var recordsUpdated = cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
When I check the value of recordsUpdated, it returns "1" but the database isn't being updated.
You need to call ExecuteNonquery which executes the statement.
// your OleDbConnection should also be wrapped in a using statement to ensure it is closed
using (OleDbConnection conn = new OleDbConnection(connectionString))
{
conn.Open(); // open the connection
using(OleDbCommand cmd = new OleDbCommand("UPDATE Data SET Title = ? WHERE ID = ?")) // wrap in using block because OleDbCommand implements IDisposable
{
cmd.CommandType = CommandType.Text;
cmd.Connection = conn;
cmd.Parameters.AddWithValue("Title", TextBox1.Text).OleDbType = OleDbType.VarChar; // Title, also set the parameter type
cmd.Parameters.AddWithValue("ID", param2).OleDbType = OleDbType.Integer; // ID, I am guessing its an integer but you should replace it with the correct OleDbType
var recordsUpdated = cmd.ExecuteNonQuery(); // execute the query
// recordsUpdated contains the number of records that were affected
}
}
The order op the Parameters that you add must match the order of the parameters in the sql statement.
Be sure you specify your OleDbType for each parameter so the command does not have to guess what it is. I guessed Title is a varchar and ID is integer, correct this if it is a wrong assumption.
You can replace "?" with parameter names to make the addition of parameters easier to read and keep the ? placeholders in the update statement. Microsoft does this in many of their examples in their documentation
ExecuteNonQuery returns the number of rows affected, capture the result and use it for debugging (see code update)
When I check the value of recordsUpdated, it returns "1" but the database isn't being updated.
If 1 is being returned then 1 record is being updated. Here are 2 trouble shooting tips.
You should make sure that your query is updating the same record you are checking. During debugging capture the value of param2 and manually use that in a select statement in Access to see the Title column of that record SELECT Title FROM Data WHERE ID = [id here]. Also get the value of TextBox1.Text in debugging and check this value against what is returned from the manually executed select query.
As this is Ms Access and the file resides on disk, make sure that you are manually checking against the same database that you are connecting to in your connection string. If you have 2 copies of the database this could easily lead to a wrong conclusion that an update is not being performed.
I m running a piece of code for scheduler in my project. But it is not working as expected.
private void Initiate_User(string strEmpCard)
{
//conn.Open();
ObjPriCmd = new SqlCommand("exec [sp_c_Initiate_Clearance] " + strEmpCard.ToString() + "", conn);
ObjPriCmd.ExecuteNonQuery();
}
The debugger stops and opens a form after my ExecuteNonQuery() line is debugged. I am not able to trace the error also. what is wrong here ??
UPDATE
My error query
insert into p_emp_clearance_hdr
(Emp_mkey,
Emp_card_no,
RA_1,
RA_2,
Depatment,
Sub_Department,
Date_of_Joining,
Resignation_date,
Last_Working_Days,
UserId)
select
em.mkey,
em.emp_card_no,
em.Reporting_To,
em.Reporting_To2,
em.Department_mkey,
em.SubDept_mkey,
convert(varchar(10), em.resig_date, 103) resig_date,
convert( varchar(10), em.Dt_Of_Join, 103) Dt_Of_Join,
convert(varchar(10), em.Dt_of_leave, 103) Dt_of_leave,
um.mkey
from emp_mst em join user_mst um
on em.mkey = um.Employee_mkey
where em.mkey = #emp_mkey
As you explained in comments, you are getting error:
ExecuteNonQuery: Connection property has not been initialized.
It means you have not initialized the connection. You have just declared it:
SqlConnection conn;
You should do like:
conn = new SqlConnection(#"you connection string");
//then your code
ObjPriCmd = new SqlCommand("exec [sp_c_Initiate_Clearance] " + strEmpCard.ToString(), conn);
ObjPriCmd.ExecuteNonQuery();
The best practice:
You should use a SqlCommand property CommandType to define that you're calling a StoredProcedure when calling from C#. And define parameters using SqlCommand .Parameters.Add it handles the SqlInjection issues itself.
conn = new SqlConnection(#"you connection string");
using (SqlCommand cmd = new SqlCommand("sp_c_Initiate_Clearance", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
// parameter name , parameter type parameter value
cmd.Parameters.Add("#parameter name", SqlDbType.VarChar).Value = strEmpCard.ToString();
con.Open();
cmd.ExecuteNonQuery();
}
You can Try it with USing Statement:-
using (SqlCommand cmd = new SqlCommand("sp_c_Initiate_Clearance", conn)) {
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#Parameter Name", Type).Value = "Value of Parameter";
conn.Open();
cmd.ExecuteNonQuery();
}
I'm playing around making a POC and I've created the following call.
public string DoStuff()
{
try
{
using (SqlDataAdapter adapter = new SqlDataAdapter())
{
SqlConnection connection = new SqlConnection("Server...");
string command = "insert into Records values (...)";
adapter.InsertCommand = new SqlCommand(command, connection);
}
}
catch (Exception exception)
{
return exception.Message + " " + exception.InnerException;
}
return "WeeHee!";
}
The text I'm seeing returned is the happy one, so I conclude there's no exceptions. Hence, I conclude that the call to the DB is performed as supposed to. However, there's no new lines in the DB being created.
I'm using the same connection string as I have in my config file and the command in pasted in from SQL Manager, where it works.
So my suspicion was that although I create an insert command, I never actually execute it but according to MSDN that's how it's supposed to work.
What stupid thing do I miss here?
You are missing connection.Open(); and adapter.InsertCommand.ExecuteNonQuery();
using (SqlDataAdapter adapter = new SqlDataAdapter())
{
SqlConnection connection = new SqlConnection("Server...");
connection.Open();
string command = "insert into Records values (...)";
adapter.InsertCommand = new SqlCommand(command, connection);
adapter.InsertCommand.ExecuteNonQuery();
}
You should use ExecuteNonQuery instead. Using an SqlDataAdapter for an INSERT query does not make sense.
Also you should Open your connection just before you execute it.
You can:
using(SqlConnection connection = new SqlConnection("Server..."))
{
SqlCommand command = connection.CreateCommand();
command.CommandText = "insert into Records values (...)";
connection.Open();
int craeted = command.ExecuteNonQuery();
}
The example you linked to returned a SQLAdapter for later use.
You don't need one at all:
using (SqlConnection connection = new SqlConnection("Server..."))
{
string command = "insert into Records values (...)";
connection.Open();
var command = new SqlCommand(command, connection);
command.ExecuteNonQuery();
}
Note that there are other execution methods, depending on expected return values and whether you want asynchronous operation: https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand(v=vs.110).aspx
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 );
}