C# OleDB Update statement not updating - c#

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.

Related

How to actually execute a command?

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

C# checking if order number already exists

I've been looking into How to check user id already exists to see how to do this.
I am trying to get this working in my code, however it's not working. I don't get errors or something, but it just write data in database even if order number already exists.
The function:
private void createorderButton_Click(object sender, EventArgs e)
{
SqlConnection myConnection = dbHelper.initiallizeDB();
String query = "INSERT INTO testtabel (knaam, korder) VALUES ('" + knaamTextBox.Text + "','" + kordernrTextBox.Text + "')";
SqlCommand sqlCommand = new SqlCommand(query, myConnection);
SqlCommand cmd = new SqlCommand("select * from testtabel where korder = #korder", myConnection);
SqlParameter param = new SqlParameter();
param.ParameterName = "#korder";
param.Value = kordernrTextBox.Text;
cmd.Parameters.Add(param);
//sqlCommand.Connection.Open();
SqlDataReader reader = sqlCommand.ExecuteReader();
if (reader.HasRows)
{
MessageBox.Show("Order already exist");
}
else
{
reader.Close();
}
// opens execute non query
int rows_inserted = sqlCommand.ExecuteNonQuery();
if (rows_inserted > 0)
{
label2.Text = "Order has been created";
}
else
{
Console.Write("Oops! Something wrong!");
}
}
Sorry for this kinda well known and duplicated question, but for some reason I can't get it working.
You called the wrong command, change
SqlDataReader reader = sqlCommand.ExecuteReader();
to
SqlDataReader reader = cmd.ExecuteReader();
The problem is here:
SqlDataReader reader = sqlCommand.ExecuteReader();
You should execute the other command first
SqlCommand cmd = new SqlCommand("select * from testtabel where korder = #korder", myConnection);
The latter command, when will be executed will tell you if there is any record in the testtabel table. If there is, then you should show the message:
Order already exist
Otherwise, you will execute your first command, that will insert the rows.
By the way, please try to avoid string concatenation, when you write sql queries. It is one of the most well known security holes. You code is open to SQL injections. You could use parameterized queries:
String query = "INSERT INTO testtabel (knaam, korder) VALUES (#knaam, #korder)";
SqlCommand sqlCommand = new SqlCommand(query, myConnection);
sqlCommand.Parameters.Add(new SqlParamete("#knaam",knaamTextBox.Text));
sqlCommand.Parameters.Add(new SqlParamete("#korder",kordernrTextBox.Text));
While your code is full of problems (magic pushbutton, SQL injections, absence of usings), there is main one. The approach you want to implement will fail on concurrent inserts, and must not be used.
Imagine, that two users run this code against the same database, using the same korder value:
1st executes SELECT - record with the given value doesn't exist;
2nd executes SELECT - record with the given value doesn't exist;
1st executes INSERT - record with the given value does exist;
2nd executes INSERT - ooops... we have a duplicate;
To avoid duplicates you must use unique indexes in database. Do not rely on your code.
You check HasRows for INSERT INTO testtabel bla...bla..bla.. not for `elect * from testtabel where korder'
Maybe you can use this (it comes from my head and not compiled, please adjust it with your own case)
private void createorderButton_Click(object sender, EventArgs e)
{
SqlConnection myConnection = dbHelper.initiallizeDB();
String query = "INSERT INTO testtabel (knaam, korder) VALUES ('" + knaamTextBox.Text + "','" + kordernrTextBox.Text + "')";
SqlCommand sqlCommand = new SqlCommand(query, myConnection);
SqlCommand cmd = new SqlCommand("select * from testtabel where korder = #korder", myConnection);
SqlParameter param = new SqlParameter();
param.ParameterName = "#korder";
param.Value = kordernrTextBox.Text;
//sqlCommand.Connection.Open();
SqlDataReader cmdReader = sqlCommand.ExecuteReader();
if (cmdReader.HasRows)
{
MessageBox.Show("Order already exist");
}
else
{
cmdReader.Close();
}
SqlDataReader reader = sqlCommand.ExecuteReader();
// opens execute non query
int rows_inserted = sqlCommand.ExecuteNonQuery();
if (rows_inserted > 0)
{
label2.Text = "Order has been created";
}
else
{
Console.Write("Oops! Something wrong!");
}
}

Insert into oracle xmltype field using oledbcommand

Is it possible to insert xml data in to an xmltype field?
I am using the following code but is throwing an error
ORA-01461: can bind a LONG value only for insert into a LONG column
.
I do not want to use ODP.NET. Can somebody give any suggestion?
OleDbConnection con = new OleDbConnection(ConfigurationManager.ConnectionStrings["OracleVAT"].ConnectionString);
try
{
string query = "update c_xml set DATA_XML = xmltype(?) where id=?";
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = con;
cmd.CommandText = query;
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("#DATA_XML", DATAXML.OuterXml);
cmd.Parameters.AddWithValue("#id", ID);
con.Open();
return cmd.ExecuteNonQuery();
}
catch
{
}
finally
{
con.Close();
}
You can also use the standard java api:
Something like this:
string query = "update c_xml set DATA_XML = xmltype(?) .....
Clob clob = conn.createClob();
clob.setString(1, req_param_xml);
statement.setClob(2, clob);

how to get the last record number after inserting record to database in access

i have database in access with auto increase field (ID).
i insert record like this (in C#)
SQL = "insert into TermNumTbl (DeviceID,IP) values ('" + DeviceID + "','" + DeviceIP + "') ";
OleDbCommand Cmd = new OleDbCommand(SQL, Conn);
Cmd.ExecuteNonQuery();
Cmd.Dispose();
Conn.Close();
how to get the last inserting number ?
i dont want to run new query i know that in sql there is something like SELECT ##IDENTITY
but i dont know how to use it
thanks in advance
More about this : Getting the identity of the most recently added record
The Jet 4.0 provider supports ##Identity
string query = "Insert Into Categories (CategoryName) Values (?)";
string query2 = "Select ##Identity";
int ID;
string connect = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|Northwind.mdb";
using (OleDbConnection conn = new OleDbConnection(connect))
{
using (OleDbCommand cmd = new OleDbCommand(query, conn))
{
cmd.Parameters.AddWithValue("", Category.Text);
conn.Open();
cmd.ExecuteNonQuery();
cmd.CommandText = query2;
ID = (int)cmd.ExecuteScalar();
}
}
I guess you could even write an extension method for OleDbConnection...
public static int GetLatestAutonumber(
this OleDbConnection connection)
{
using (OleDbCommand command = new OleDbCommand("SELECT ##IDENTITY;", connection))
{
return (int)command.ExecuteScalar();
}
}
I like more indicate the type of command
is very similar to the good solution provided by Pranay Rana
using (OleDbCommand cmd = new OleDbCommand())
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = sql_Insert;
cmd.ExecuteNonQuery();
cmd.CommandText = sql_obtainID;
resultado = (int)comando.ExecuteScalar();
}
query = "Insert Into jobs (jobname,daterecieved,custid) Values ('" & ProjectNAme & "','" & FormatDateTime(Now, DateFormat.ShortDate) & "'," & Me.CustomerID.EditValue & ");"'Select Scope_Identity()"
' Using cn As New SqlConnection(connect)
Using cmd As New OleDb.OleDbCommand(query, cnPTA)
cmd.Parameters.AddWithValue("#CategoryName", OleDb.OleDbType.Integer)
If cnPTA.State = ConnectionState.Closed Then cnPTA.Open()
ID = cmd.ExecuteNonQuery
End Using
Using #Lee.J.Baxter 's method (Which was great as the others id not work for me!) I escaped the Extension Method and just added it inline within the form itself:
OleDbConnection con = new OleDbConnection(string.Format(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source='{0}'", DBPath));
OleDbCommand cmd = con.CreateCommand();
con.Open();
cmd.CommandText = string.Format("INSERT INTO Tasks (TaskName, Task, CreatedBy, CreatedByEmail, CreatedDate, EmailTo, EmailCC) VALUES('{0}','{1}','{2}','{3}','{4}','{5}','{6}')", subject, ConvertHtmlToRtf(htmlBody), fromName, fromEmail, sentOn, emailTo, emailCC);
cmd.Connection = con;
cmd.ExecuteScalar();
using (OleDbCommand command = new OleDbCommand("SELECT ##IDENTITY;", con))
{
ReturnIDCast =(int)command.ExecuteScalar();
}
NOTE: In most cases you should use Parameters instead of the string.Format() method I used here. I just did so this time as it was quicker and my insertion values are not coming from a user's input so it should be safe.
Simple,
What we do in excel for copy text in above cell?
Yes, just ctrl+" combination,
and yes, it's work in MS ACCESS also.
You can use above key stroke combination for copy above records field text, just make sure if you have duplicate verification applied or edit field data before move next field.
If you aspects some more validation or any extraordinary then keep searching stack overflow.

ASP.net why are these queries not executing?

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.

Categories

Resources