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.
Related
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 looked into materials in www.npgsql.org, but couldn't find how to solve my problem...
Table, PostgreSQL
[City], [State]
"Austin", "TX"
"Houston", "TX"
"Los Angeles", "CA"
"San Diego", "CA"
"San Fransisco";"CA"
"St.Louis", "MO"
Function (stored procedure), PostgreSQL
-- Procedure that returns a single result set (cursor)
CREATE OR REPLACE FUNCTION show_cities() RETURNS refcursor AS $$
DECLARE
ref refcursor;
BEGIN
OPEN ref FOR SELECT city, state FROM cities;
RETURN ref;
END;
$$ LANGUAGE plpgsql;
Code, C#
using (NpgsqlConnection conn = new NpgsqlConnection(ConfigurationManager.ConnectionStrings["dbConnection"].ConnectionString))
{
conn.Open();
using (NpgsqlTransaction tran = conn.BeginTransaction())
{
using (var command = new NpgsqlCommand("show_cities", conn))
{
command.Transaction = tran;
command.CommandType = CommandType.StoredProcedure;
NpgsqlDataReader dr = command.ExecuteReader();
while (dr.Read())
str += dr.GetValue(0);
dr.Close();
}
tran.Commit();
}
}
This returns "unnamed portal 1" and it's a cursor to be fetched not data,
Is there any way to convert this to data like Austin, Houston, Los Angeles... ?
There are some posts over internet about this, but I'm not sure what I'm doing wrong.
npgsql : ver3.0.3
c# : vs2012
(added)
I have found this is happening at npgsql ver3.x, while in ver2.x it is working fine with my code. Is there any change in usage for fetching cursor ?
(reference)
http://www.sqlines.com/postgresql/npgsql_cs_result_sets
With Shay's help, I figured out how we can fetch cursor in v3.x after removal of "dereferenced" feature.
I think there are not much of good example on this, I hope this might help people save time to search example.
You can do this in npgsql ver3.x
1. CommandType.StoredProcedure (cursor name not defined)
conn.Open();
NpgsqlTransaction tran = conn.BeginTransaction();
NpgsqlCommand command = new NpgsqlCommand("show_cities", conn);
command.CommandType = CommandType.StoredProcedure;
command.ExecuteNonQuery();
command.CommandText = "fetch all in \"<unnamed portal 1>\"";
command.CommandType = CommandType.Text;
NpgsqlDataReader dr = command.ExecuteReader();
while (dr.Read())
{
// do what you want with data, convert this to json or...
Console.WriteLine(dr[0]);
}
dr.Close();
tran.Commit();
conn.Close();
2. CommandType.StoredProcedure (cursor name defined)
conn.Open();
NpgsqlTransaction tran = conn.BeginTransaction();
NpgsqlCommand command = new NpgsqlCommand("select show_cities(#ref)", conn);
command.CommandType = CommandType.Text;
NpgsqlParameter p = new NpgsqlParameter();
p.ParameterName = "#ref";
p.NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Refcursor;
p.Direction = ParameterDirection.InputOutput;
p.Value = "ref";
command.Parameters.Add(p);
command.ExecuteNonQuery();
command.CommandText = "fetch all in \"ref\"";
command.CommandType = CommandType.Text;
NpgsqlDataReader dr = command.ExecuteReader();
while (dr.Read())
{
// do what you want with data, convert this to json or...
Console.WriteLine(dr[0]);
}
dr.Close();
tran.Commit();
conn.Close();
3. CommandType.Text (cursor name defined)
conn.Open();
NpgsqlTransaction tran = conn.BeginTransaction();
NpgsqlCommand command = new NpgsqlCommand("select show_cities(#ref)", conn);
command.CommandType = CommandType.Text;
NpgsqlParameter p = new NpgsqlParameter();
p.ParameterName = "#ref";
p.NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Refcursor;
p.Direction = ParameterDirection.InputOutput;
p.Value = "ref";
command.Parameters.Add(p);
command.ExecuteNonQuery();
command.CommandText = "fetch all in \"ref\"";
command.CommandType = CommandType.Text;
NpgsqlDataReader dr = command.ExecuteReader();
while (dr.Read())
{
// do what you want with data, convert this to json or...
Console.WriteLine(dr[0]);
}
dr.Close();
tran.Commit();
conn.Close();
(reference for v2.x) http://www.sqlines.com/postgresql/npgsql_cs_result_sets
This is example for easy understanding, so if you want your function to return single result set, then instead of returning cursor, please consider it to return table as #Shay suggested or create a view not a function as #CeOnSql suggested.
Thanks !
Npgsql 2.x had a feature whereby it automatically "dereferenced" cursors returned from functions. This feature was dropped from Npgsql 3.0; this is mentioned in our migration nodes for 3.0, and the discussion is in this issue. Since the cursor is simply returned and isn't dereferenced, Npgsql returns the cursor name itself (unnamed portal 1); you can now fetch results from this query by sending FETCH etc.
However, as was mentioned, wrapping a single SELECT in a function doesn't make much sense. If you do need to write a function that returns a single resultset, make it return a SETOF or a TABLE instead of a cursor: CREATE FUNCTION ... RETURNS TABLE (column_name column_type [, ...]). Apart from being simpler and cleaner, this is also more efficient, as the query results are returned directly (dereferencing the cursor involves another database roundtrip).
See the PostgreSQL docs for more info on how to define a function returning a table.
I have following working code with Npgsql 2.2.7 version:
private static DataSet ExecuteFunction(string functionName)
{
DataSet ds = new DataSet();
var conn = new NpgsqlConnection("replace with connection string");
conn.Open();
var tran = conn.BeginTransaction();
var cmd = new NpgsqlCommand(functionName, conn);
cmd.CommandType = CommandType.StoredProcedure;
NpgsqlDataAdapter da = new NpgsqlDataAdapter(cmd);
da.Fill(ds);
//foreach (DataRow r in ds.Tables[0].Rows)
//{
// Console.WriteLine("{0}", r[0]);
//}
tran.Commit();
conn.Close();
return ds;
}
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.