I've Edited this question to prevent asking another. I'm trying to update a datatable in MS Access using an UPDATE query and Parameters. The code doesn't give an error and runs fine, but it does't save the updated data and I can't work out why.
Here's the code I'm using :
if (Editing)
{
string Query = "UPDATE [Employee] SET PayrollNo=#PayrollNo, FirstName=#FirstName, LastName=#LastName, AnnualHolidayEntitlement=#AnnualHolidayEntitlement, DaysTakenToDate=#DaysTakenToDate WHERE PayrollNo = #SentPayroll";
string ConnString = "Provider = Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\\HoliPlanData.accdb;Persist Security Info=False";
using (OleDbConnection conn = new OleDbConnection(ConnString))
using (OleDbCommand UpdateEmployee = new OleDbCommand(Query, conn))
{
conn.Open();
UpdateEmployee.Parameters.AddWithValue("#SentPayroll", OleDbType.Integer).Value = Convert.ToInt32(PassPayrollNo);
UpdateEmployee.Parameters.AddWithValue("#PayrollNo", OleDbType.Integer).Value = Convert.ToInt32(TxtPayrollNo.Text);
UpdateEmployee.Parameters.AddWithValue("#FirstName", OleDbType.VarChar).Value = TxtFirstName.Text;
UpdateEmployee.Parameters.AddWithValue("#LastName", OleDbType.VarChar).Value = TxtLastName.Text;
UpdateEmployee.Parameters.AddWithValue("#AnnualHolidayEntitlement", OleDbType.Integer).Value = Convert.ToInt32(TxtAHE.Text);
UpdateEmployee.Parameters.AddWithValue("#DaysTakenToDate", OleDbType.Integer).Value = Convert.ToInt32(TxtDTTD.Text);
UpdateEmployee.ExecuteScalar();
BtnSubmit.Enabled = false;
MessageBox.Show("Data Edited Successfully");
}
How can I change this code so that it works? Thanks in advance.
EDIT/ANSWER.
I didn't know and chances are if you're having problems with an UPDATE query you may not know it either. When adding parameters you need to add them in the same order they are called in the query. In my code the first parameter should be added last, since it is last in the stringQuery. I moved it and it worked fine!
Why does invoking my UPDATE query in an Access database via OleDb not work?
If anyone else has this issue with UPDATE queries, It took me too long to find this question, where someone clears it up great.
Related
I don't know what am I doing wrong but I tried everything I found on net, the code doesn't give any errors but also doesn't update database.
UPDATED:I solved the problem with taking #no to [] brackets
Here is code :`
String query = "UPDATE Kitaplık SET kitapAdi=#ad,kitapYazari=#yazar,kitapYayinevi=#yayinevi,sayfaSayisi=#sayfaSayisi where no=#no";
con = new OleDbConnection("Provider=Microsoft.ACE.Oledb.12.0;Data Source=Kutuphane.accdb");
cmd = new OleDbCommand(query, con);
cmd.Parameters.AddWithValue("#ad", kitapAdiText.Text);
cmd.Parameters.AddWithValue("#yazar", kitapYazariText.Text);
cmd.Parameters.AddWithValue("#yayinevi", kitapYayıneviText.Text);
cmd.Parameters.AddWithValue("#sayfaSayisi", Convert.ToInt32(sayfaSayisiText.Text));
cmd.Parameters.AddWithValue("#no", Convert.ToInt32(noText.Text));
con.Open();
cmd.ExecuteNonQuery();
con.Close();
listBox1.Items.Clear();
bilgileriCek();
Thanks for the answers!
OP "solved the problem with taking (changing) #no to [] brackets."
I am building an application for a group of friends and myself to use for DnD sessions. Part of the program involves taking all of the values that are entered for our characters, items, etc and storing them to a database. I have the database built, and am pulling from the database into the program, however I am unable to return data to the database. I have the data coming into a dataset, and all of my edits are affecting the dataset, but I cannot get anything to affect the actual source database tables.
Below I have the button that I intend to use to update items in the characters' packs. I have both dataadapter, and tableadapter methods included that I have tried.
private void btnaddpack_Click(object sender, EventArgs e)
{
if (txtbxpack.Text != "")
{
/*connection.Open();
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "UPDATE Pack SET Item = (#ItemName)" + "WHERE Id = '" + this.lstpack.SelectedValue + "';";
cmd.ExecuteNonQuery();
cmd.Clone();*/
string packitem = txtbxpack.Text; //will take item from an textbox
this.packTableAdapter.Insert(packitem);
this.Validate();
this.packBindingSource.EndEdit();
this.packTableAdapter.Update(this.dnD_MachineDataSet.Pack);
}
PopulatePack();
Here is my populate code in case someone needs that:
private void PopulatePack()
{
using (connection = new SqlConnection(connectionString)) //this is all about opening the connection to the sqldatabase, normally it would need to be closed, but this uses idisposable, so it will close itself
using (SqlDataAdapter adapter = new SqlDataAdapter("SELECT * FROM Pack", connection))
{
DataTable packtable = new DataTable();
adapter.Fill(packtable);
lstpack.DataSource = packtable;
lstpack.DisplayMember = "Item";
lstpack.ValueMember = "Id";
}
}
As mentioned above, all of the changes are appearing whenever I re-populate the listboxes that draw upon the dataset, hence why this is an issue of trying to get that data back into the source database. I will make the obligatory "I'm relatively new to using databases" statement as it will do no good to pretend that I am an expert.
Thanks.
In the commented code, you would need to do the following:
assign the connection object to the SqlCommand object's Connection
property
pass the item name to your #ItemName parameter
assign a parameter value to the 'Id' column in the WHERE clause
remove, 'cmd.Clone();', and replace with, 'connection.Close();'
Here is what the code should look like:
connection.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = connection;
cmd.CommandText = "UPDATE Pack SET Item = (#ItemName) WHERE Id = #ID;";
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("#ItemName", txtbxpack.Text);
cmd.Parameters.AddWithValue("#ID", this.lstpack.SelectedValue);
cmd.ExecuteNonQuery();
connection.Close();
I'm trying to update a CLOB column in my database with a long string containing the HTML contents of an email. There are 18,000 characters in the record I'm having an issue with.
The below code will work if I set the html variable to "short string". But if I try to run the code with the long 18,000 character HTML string, I get this error: "Oracle.DataAccess.Client.OracleException ORA-22922: nonexistent LOB value ORA-02063: preceding line from ((servername))"
public static void UpdateHtmlClob(string html, string taxId,string un, string pw)
{
using (OracleConnection conn = new OracleConnection())
{
try
{
conn.ConnectionString = "User Id=" + un + ";Password=" + pw + ";Data Source=server.com;";
conn.Open();
OracleCommand cmd = new OracleCommand();
string indata = html;
cmd.CommandText = "UPDATE table1 SET HTML_BODY = :clobparam";
OracleParameter clobparam = new OracleParameter("clobparam", OracleDbType.Clob, indata.Length);
clobparam.Direction = ParameterDirection.Input;
clobparam.Value = indata;
cmd.Parameters.Add(clobparam);
cmd.Connection = conn;
cmd.ExecuteNonQuery();
conn.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
conn.Close();
}
}
}
Before you edited your code to reflect my answer, there were two problems with your code that I saw.
Firstly, you need to use a colon in your command text to tell Oracle that clobparam is a bind variable, not a column name:
cmd.CommandText = "UPDATE table1 SET HTML_BODY = :clobparam";
Secondly, you were not setting the database connection anywhere on the command. Which connection should the command be using? In your situation you have only one connection but more generally it may be possible to have more than one connection open. Add the line
cmd.Connection = connection;
or alternatively create the command using
OracleCommand cmd = connection.CreateCommand();
Of course, it would be nice if Oracle.DataAccess returned an error message that gave you the slightest hint that this was what you were doing wrong.
Anyway, now that you've edited your question to include the critical detail ORA-02063: preceding line from ((servername)), which tells us that you are using a database link, all I can really do is echo what I wrote in the comment: connect direct to the remote database to transfer LOB data, don't use a database link.
I want to get into developing applications that use databases. I am fairly experienced (as an amateur) at web based database utilization (mysql, pdo, mssql with php and old style asp) so my SQL knowledge is fairly good.
Things I have done already..
Create forms application
Add four text boxes (first name, last name, email, phone)
Added a datagrid control
Created a database connection using 'Microsoft SQL Server Database File (SqlClient)'
Created a table with fields corresponding to the four text boxes.
What I want to be able to do now is, when a button is clicked, the contents of the four edit boxes are inserted using SQL. I don't want to use any 'wrapper' code that hides the SQL from me. I want to use my experience with SQL as much as possible.
So I guess what I am asking is how do I now write the necessary code to run an SQL query to insert that data. I don't need to know the SQL code obviously, just the c# code to use the 'local database file' connection to run the SQL query.
An aside question might be - is there a better/simpler way of doing this than using the 'Microsoft SQL Server Database File' connection type (I have used it because it looks like it's a way to do it without having to set up an entire sql server)
The below is inserting data using parameters which I believe is a better approach:
var insertSQL = "INSERT INTO yourTable (firstName, lastName, email, phone) VALUES (firstName, lastName, email, phone)";
string connectionString = "Data Source=myServerAddress;Initial Catalog=myDataBase;Integrated Security=SSPI; User ID=userid;Password=pwd;"
using (var cn = new SqlCeConnection(connectionString))
using (var cmd = new SqlCeCommand(insertSQL, cn))
{
cn.Open();
cmd.Parameters.Add("firstName", SqlDbType.NVarChar);
cmd.Parameters.Add("lastName", SqlDbType.NVarChar);
cmd.Parameters.Add("email", SqlDbType.NVarChar);
cmd.Parameters.Add("phone", SqlDbType.NVarChar);
cmd.Parameters["firstName"].Value = firstName;
cmd.Parameters["lastName"].Value = lastName;
cmd.Parameters["email"].Value = email;
cmd.Parameters["phone"].Value = phone;
cmd.ExecuteNonQuery();
}
This is selecting data from database and populating datagridview:
var dt = new DataTable();
string connectionString = "Data Source=myServerAddress;Initial Catalog=myDataBase;Integrated Security=SSPI; User ID=userid;Password=pwd;"
using (var cn = new SqlCeConnection(connectionString )
using (var cmd = new SqlCeCommand("Select * From yourTable", cn))
{
cn.Open();
using (var reader = cmd.ExecuteReader())
{
dt.Load(reader);
//resize the DataGridView columns to fit the newly loaded content.
yourDataGridView.AutoSize = true; yourDataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
//bind the data to the grid
yourDataGridView.DataSource = dt;
}
}
This first example is an over view based upon how I think it will be easier to understand but this is not a recommended approach due to vulnerability to SQL injection (a better approach further down). However, I feel it is easier to understand.
private void InsertToSql(string wordToInsert)
{
string connectionString = Data Source=myServerAddress;Initial Catalog=myDataBase;Integrated Security=SSPI; User ID=myDomain\myUsername;Password=myPassword;
string queryString = "INSERT INTO table_name (column1) VALUES (" + wordToInsert + ")"; //update as you feel fit of course for insert/update etc
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open()
SqlDataAdapter adapter = new SqlDataAdapter();
SqlCommand command = new SqlCommand(queryString, connection);
command.ExecuteNonQuery();
connection.Close();
}
}
I would also suggest wrapping it in a try/catch block to ensure the connection closes if it errors.
I am not able to test this but I think it is OK!
Again don't do the above in live as it allows SQL injection - use parameters instead. However, it may be argued it is easier to do the above if you come from PHP background (just to get comfortable).
This uses parameters:
public void Insert(string customerName)
{
try
{
string connectionString = Data Source=myServerAddress;Initial Catalog=myDataBase;Integrated Security=SSPI; User ID=myDomain\myUsername;Password=myPassword;
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
connection.Open() SqlCommand command = new SqlCommand( "INSERT INTO Customers (CustomerName" + "VALUES (#Name)", connection);
command.Parameters.Add("#Name", SqlDbType.NChar, 50, " + customerName +");
command.ExecuteNonQuery();
connection.Close();
}
catch()
{
//Logic in here
}
finally()
{
if(con.State == ConnectionState.Open)
{
connection.Close();
}
}
}
And then you just change the SQL string to select or add!
Currently I have The following code:
void Page_Load(object sender, System.EventArgs e)
{
string connectionString = "server=abc;database=abc;uid=abc;pwd=1234";
SqlConnection mySqlConnection = new SqlConnection(connectionString);
string procedureString = "Callin_Insert";
SqlCommand mySqlCommand = mySqlConnection.CreateCommand();
mySqlCommand.CommandText = procedureString;
mySqlCommand.CommandType = CommandType.StoredProcedure;
mySqlCommand.Parameters.Add("#LVDate", SqlDbType.DateTime).Value = DateTime.Now;
mySqlCommand.Parameters.Add("#LVTime", SqlDbType.DateTime).Value = DateTime.Now;
mySqlCommand.Parameters.Add("#CuID", SqlDbType.Int).Value = CustID;
mySqlCommand.Parameters.Add("#Type", SqlDbType.Int).Value = Keypress;
mySqlConnection.Open();
mySqlCommand.ExecuteNonQuery();
SqlDataAdapter mySqlDataAdapter = new SqlDataAdapter();
mySqlDataAdapter.SelectCommand = mySqlCommand;
mySqlConnection.Close();
}
Basically, I am opening a connection to the Database during the page_load. I am also closing that connection in page_load. Part of my problem is that the CustID & Keypress are not getting passed, because they occur later in the page life cycle. What is the best way to open the connection, get the 2 variables (when I they are entered by the user), pass them to the database, and close the connection.
Somethings I have tried is running it _OnLoad. But this didn't work either.
Any thoughts or suggestion, are greatly appreciated.
First of SqlConnection is of IDisposible interface means it is much safer to wrap your code with using statement like this.
string connectionString = "server=abc;database=abc;uid=abc;pwd=1234";
using (SqlConnection mySqlConnection = new SqlConnection(connectionString))
{
string procedureString = "Callin_Insert";
SqlCommand mySqlCommand = new SqlCommand(procedureString, mySqlConnection);
mySqlCommand.CommandType = CommandType.StoredProcedure;
mySqlCommand.Parameters.Add("#LVDate", SqlDbType.DateTime).Value = DateTime.Now;
mySqlCommand.Parameters.Add("#LVTime", SqlDbType.DateTime).Value = DateTime.Now;
mySqlCommand.Parameters.Add("#CuID", SqlDbType.Int).Value = CustID;
mySqlCommand.Parameters.Add("#Type", SqlDbType.Int).Value = Keypress;
mySqlConnection.Open();
mySqlCommand.ExecuteNonQuery();
//i have no idea what does this mean, data adapter is for filling Datasets and DataTables
SqlDataAdapter mySqlDataAdapter = new SqlDataAdapter();
mySqlDataAdapter.SelectCommand = mySqlCommand;
}
Second of all i offer you to use SqlDataSourceObject control which will make much easier to work with cases like yours.
It will know how to deal with Page.IsPostBack that you haven't implemented but should, paging and other stuff you need.
Think there are a few problems here... first of all why are you running your query and then passing it to a data adapter? The data adapter will run the select command when queried.
I suggest creating a SqlDataSource on your aspx page (not code behind) and bind your control to it. Then hook up the Selecting event and in there populate your parameters. That should happen later in the page lifecycle so your parameter values will then be set.