I'm using Visual Studio 2010 to create a Win Form in c#. It has a handful of Comboboxes, and textboxes that the user can fill out and then submit to an Access DB. My issue comes in when I try to update existing entries. I load an existing entry, make my changes and click update. I do not get any system errors, my connection to the DB is successful, but no changes are actually made to the data. Am I completely missing something? Thanks in advance for any help or insight.
Here is the code for the update button:
private void updateButton_Click_1(object sender, EventArgs e)
{
{
OleDbConnection conn = new OleDbConnection();
conn.ConnectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\servicereq1.mdb";
OleDbCommand cmd = new OleDbCommand("UPDATE servicereq SET DateLogged = #datelogged, LoggedBy = #loggedby, Function = #function, [Other Impacts] = #summary, Account = #earningsaccount, [From] = #from, [To] = #to, Description = #description, Fixer = #fixer, [Time Estimate] = #timeestimate, [Actual Start] = #actualstart, [Actual Finish] = #actualfinish, [Actual Time] = #actualtime, [Programs/Forms] = #programsforms, Comments = #comments, [Retest Date] = #requestdate, Tester = #tester, Status = #status, [Problem In Environment] = #problemfoundin, [Code In Environment] = #codein WHERE (ServiceRequestNumber = #servreq)");
cmd.Connection = conn;
conn.Open();
if (conn.State == ConnectionState.Open)
{
cmd.Parameters.AddWithValue("#servreq", serviceRequestNumberTextBox.Text);
cmd.Parameters.AddWithValue("#datelogged", dateLoggedTextBox.Text);
cmd.Parameters.AddWithValue("#loggedby", loggedByComboBox.Text);
cmd.Parameters.AddWithValue("#problemfoundin", problem_In_EnvironmentComboBox.Text);
cmd.Parameters.AddWithValue("#function", functionTextBox.Text);
cmd.Parameters.AddWithValue("#summary", other_ImpactsTextBox.Text);
cmd.Parameters.AddWithValue("#earningsaccount", accountTextBox.Text);
cmd.Parameters.AddWithValue("#from", fromTextBox.Text);
cmd.Parameters.AddWithValue("#to", toTextBox.Text);
cmd.Parameters.AddWithValue("#status", statusComboBox.Text);
cmd.Parameters.AddWithValue("#description", descriptionTextBox.Text);
cmd.Parameters.AddWithValue("#fixer", fixerComboBox.Text);
cmd.Parameters.AddWithValue("#codein", code_In_EnvironmentComboBox.Text);
cmd.Parameters.AddWithValue("#programsforms", programs_FormsTextBox.Text);
cmd.Parameters.AddWithValue("#timeestimate", time_EstimateTextBox.Text);
cmd.Parameters.AddWithValue("#actualstart", actual_StartTextBox.Text);
cmd.Parameters.AddWithValue("#actualfinish", actual_FinishTextBox.Text);
cmd.Parameters.AddWithValue("#actualtime", actual_TimeTextBox.Text);
cmd.Parameters.AddWithValue("#requestdate", retest_DateTextBox.Text);
cmd.Parameters.AddWithValue("#tester", testerComboBox.Text);
cmd.Parameters.AddWithValue("#comments", commentsTextBox.Text);
try
{
cmd.ExecuteNonQuery();
MessageBox.Show("Form Updated Successfully");
conn.Close();
}
catch (OleDbException ex)
{
MessageBox.Show(ex.Message);
conn.Close();
}
}
else
{
MessageBox.Show("Connection Failed");
}
}
}
You shouldn't put your database parameters within quotes - they are evaluated as plain text instead of parameters if you do. There is no row where ServiceRequestNumber equals the literal string '#servreq', so nothing is updated.
Also, DataCommands don't pull in local variables as parameters - they must be explicitly added to the DataCommand object (cmd in this case). The reason you aren't getting any errors when you remove your parameter-adding code is because, as stated above, the query doesn't expect any parameters.
Also, the way parameters are being added in the code you removed is strange to say the least. This is much more normal, and significantly easier to read:
cmd.Paramaters.AddWithValue("#paramName", paramData);
//or
cmd.Parameters.Add(new OleDbParameter("#paramName", paramData));
After spending a little more time editing and moving code around, I stumbled on the fact that your parameters must be in the same order in the query as they are when you bind values to them. After making syntactical changes suggested by JoFlash Studios and putting my parameters in the correct order, I was able to make edits to existing data in my form.
Related
private void button1_Click(object sender, EventArgs e)
{
string CS = ConfigurationManager.ConnectionStrings["connection_string"].ConnectionString;
OleDbConnection C = new OleDbConnection(CS);
C.Open();
OleDbCommand CMD = new OleDbCommand("", C);
CMD.CommandText = "SELECT COUNT(*) FROM Applicants WHERE ApplicantID = ?";
CMD.Parameters.AddWithValue("#ApplicantID", textBox1.Text);
if (Convert.ToInt32(CMD.ExecuteScalar()) > 0)
{
CMD.CommandText = "UPDATE Onboarding SET " +
"BackgroudCheck = #BGC, PhotoID = #PID, " +
"TrainingHoursOutOf40 = #THOO, DrugTestTaken = #DTT, PassedDrugTest = #PDT" +
"WHERE ApplicantID = #AID";
CMD.Parameters.AddWithValue("#AID", textBox1.Text);
CMD.Parameters.AddWithValue("#BGC", CheckBox1);
CMD.Parameters.AddWithValue("#PID", CheckBox2);
CMD.Parameters.AddWithValue("#THOO", TextBox2.Text);
CMD.Parameters.AddWithValue("#DTT", CheckBox3);
CMD.Parameters.AddWithValue("#PDT", CheckBox4);
MessageBox.Show("Applicant Updated Successfully");
}
else
{
MessageBox.Show("Applicant Does Not Exists");
}
C.Close();
}
I am trying to update the data table. Some how when I try to update in the form I do get a messagebox saying "Applicant updated Successfully", but when I go to the data table or view it in another form, the table is not updated.
Several problems here
Ole does not use named parameters. You can give your parameters names but they're ignored. You must add the right number of parameters in the right order
use using to ensure database resources are closed and disposed of when you're done with them
You never actually executed your UPDATE query
You didn't put .Checked to retrieve the Booleans from your check boxes
You don't need to SELECT first. If the update updates no record the applicant doesn't exist. An UPDATE doesn't error if there is nothing to update. ExecuteNonQuery returns an int of how many rows were updated
You really should rename your controls after you drop them on the form. Code that is full of Label57, Button29 is effectively obfuscated (meaningless garbage) that is very hard to maintain
In c# variables declared inside a method are named with camelCaseLikeThis, not ALLCAPS
Be aware that if this is a file based database you're using (it is likely Access if it's ole) that multiple copies of the database file are present on disk. Countless questions are asked "why isn't my db updating" when it is - it's just that the program is updating the db in the bin folder and the dev is looking in the copy of the db in the project folder (which is copied over the top of the bin folder db every time the project is run, which is another reason the program "never remembers anything")
if you're using Access, you would do yourself massive favors by switching to an extensively used commercial grade db (sql server Express is free, and SQLite is definitely worth using over Access) and learning entity framework. I appreciate you're on a learning journey but largely what you're learning now isn't widely used in the real world any more, because it's a tedious waste of time somewhat akin to writing your own graphics drivers or Json parsers. If you want to stick with this approach take a look at Dapper, which takes a lot of the pain out of "data access by SQL strings in button click handlers" - opening and closing connections, filling in parameters and types, pulling data out of readers and casting it; all that work can be done by software and dapper can reduce the code you've written here to a single line like c.Execute("UPDATE ...", new { bgcCheckbox.Checked, ... aidTextbox.Text })
private void button1_Click(object sender, EventArgs e)
{
string cs = ConfigurationManager.ConnectionStrings["connection_string"].ConnectionString;
using(OleDbConnection c = new OleDbConnection(cs)){
c.Open();
using(OleDbCommand cmd = new OleDbCommand("", c)){
cmd.CommandText = "UPDATE Onboarding SET " +
"BackgroudCheck = ?, PhotoID = ?, " +
"TrainingHoursOutOf40 = ?, DrugTestTaken = ?, PassedDrugTest = ?" +
"WHERE ApplicantID = ?";
cmd.Parameters.AddWithValue("#BGC", CheckBox1.Checked);
cmd.Parameters.AddWithValue("#PID", CheckBox2.Checked);
cmd.Parameters.AddWithValue("#THOO", TextBox2.Text);
cmd.Parameters.AddWithValue("#DTT", CheckBox3.Checked);
cmd.Parameters.AddWithValue("#PDT", CheckBox4.Checked);
cmd.Parameters.AddWithValue("#AID", textBox1.Text);
if(cmd.ExecuteNonQuery()>0)
MessageBox.Show("Applicant Updated Successfully");
else
MessageBox.Show("Applicant Does Not Exists");
}
}
}
You have not used ExecuteNonQuery() method of SQL Command class.
int returnValue;
returnValue = CMD.ExecuteNonQuery();
No exceptions, everything gets executed but the update doesn't happen!
Everything works ok when I have just #JIR parameter but now I added #Paragon and the update doesn't do it's job. No exception whatsoever data passed is OK...
I don't see anything wrong with this query does anyone know what could possibly be going wrong?
private static void InsertJIR(FisDnevni racun)
{
using (OleDbConnection con = new OleDbConnection(RegistarBlagajna.Modul.VezaNaBazu.ConnectionString))
{
try
{
con.Open();
OleDbCommand cmd = new OleDbCommand(#"
UPDATE FisDnevni
SET [JIR] = #JIR,
[Paragon] = #Paragon
WHERE BrojRacuna = #BrojRacuna"
, con);
cmd.Parameters.AddWithValue("#JIR", racun.JIR.Substring(0,37));
cmd.Parameters.AddWithValue("#BrojRacuna", racun.BrojRacuna);
cmd.Parameters.AddWithValue("#Paragon", racun.Paragon);
cmd.ExecuteNonQuery();
con.Close();
}
catch (Exception)
{
throw;
}
}
}
This is a good old problem - ensure the query parameters in OleDbParameter are declared in proper order like this:
using (OleDbConnection con = new OleDbConnection(RegistarBlagajna.Modul.VezaNaBazu.ConnectionString))
{
try
{
con.Open();
using (OleDbCommand cmd = new OleDbCommand(#"UPDATE FisDnevni SET [JIR] = #JIR, [Paragon] = #Paragon WHERE BrojRacuna = #BrojRacuna", con)
{
cmd.Parameters.AddWithValue("#JIR", racun.JIR.Substring(0,37));
// this must be the second parameter instead of third one
cmd.Parameters.AddWithValue("#Paragon", racun.Paragon);
cmd.Parameters.AddWithValue("#BrojRacuna", racun.BrojRacuna);
cmd.ExecuteNonQuery();
con.Close();
}
}
catch (Exception)
{
throw;
}
}
Note that OLE DB .NET Provider doesn't recognize named parameters for OleDbCommand when CommandType is set to Text, but it apparently does recognize the parameter order, hence as long as they're passed in proper order, it'll accepted as query parameter.
Related issue:
how to update a table using oledb parameters?
maybe i've just never used it, but why is there an # here?
OleDbCommand(#"
i also havent worked with C# in a while but is multi-line concatenation possible without a + or something?
thirdly why are you using [] on these column names? i don't see any special characters or spaces.
this post is sounding a lot more dikkish than i mean it to be, im not trying, just legit curious
As a beginner to c#, and I actaully spent a lot of time researching this:
I cannot add some data into the database, I can extract data from it, but cannot add anything into the database. I use sql server as my database.
try {
fname = fname_tb.Text;// first name
sname = sname_tb.Text; // second name
q = "insert into beforebath1(firstname,secondname) values(#fname,#sname)";
conn_string = Properties.Settings.Default.beforebath_connection_string;
SqlConnection co = new SqlConnection(conn_string);
SqlCommand cmd;
co.Open();
cmd = new SqlCommand(q, co);
cmd.Connection = co;
cmd.Parameters.AddWithValue("#fname", fname_tb.Text);
cmd.Parameters.AddWithValue("#sname", sname_tb.Text);
cmd.ExecuteNonQuery();
co.Close();
}
catch(Exception err) {
MessageBox.Show(err.toString());
}
my sql connection string is this:
Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\beforebath_db.mdf;Integrated Security=True;Connect Timeout=30
It is automatically generated when I created the database. Please help me insert the text in the two textboxes (fname_tb.Text and sname_tb.Text) into the table called beforebath1 of the database called beforebath_db.mdf.
Is it something to do with my data directory?
I see a couple of mistakes in your code.
First, why catch an exception that will only be shown in a message?
It is often best to let the exception bubble up to have the stack trace in debug. This is not the same if this is production code, which I doubt.
Second, make sure to dispose your objects adequately.
The Using Statement is the most prefered way to work with disposeable items such as a database connection and a command.
using (var cnx = new SqlConnection(connectionString)) {
cnx.Open();
var sql = #"insert into beforebath1 (first_name, second_name)
values (#fname, #lname)";
using (var cmd = new SqlCommand(sql, cnx)) {
cmd.Parameters.AddWithValue("#fname", fname_tb.Text);
cmd.Parameters.AddWithValue("#lname", lname_tb.Text);
try {
int rowsAffected = cmd.ExecuteNonQuery();
if (0 < rowsAffected) MessageBox.Show("Success!");
else MessageBox.Show("Failed!");
} catch (SqlException ex) {
// It is almost prefered to let the exception be thrown freely
// so that you may have its full stack trace and have more
// details on your error.
MessageBox.Show(ex.Message);
} finally {
if (cnx.State == ConnectionState.Open) cnx.Close();
}
}
}
This way, wrapping your disposable objects within using blocks, you make sure that everything is getting to get disposed automatically when exiting the code block.
As for your "it doesn't work" problem, I guess the problem be either at the connection string level, or at your table_name level.
You wish to insert into beforebath1, and your insert statement states table_name. Make sure you put the right table name where it belongs so that it may work properly.
Can you change you connection string to this:
Server=(LocalDB)\v11.0;Database=beforebath_db;Trusted_Connection=True;
This means the your app and other programs using the Db will all share the same instance.
Also, as mentioned by #Will, you should wrap your SQLConnection in a using statement for garbage collection.
For better implementations you can use stored_procedures like bellow:
Step1: Declare Stored Procedure for your Query:
CREATE PROCEDURE [dbo].[ADD_TO_BEFORE_PATH_SP]
/*Type of this variables should be their column types*/
#fname varchar(MAX),
#lname varchar(MAX)
AS
BEGIN
INSERT INTO [dbo].[beforebath1] (fname, lname)
VALUES (#fname,#lname)
END
Step2: Using Stored Procedure where you need:
SqlConnection con = new SqlConnection(connectionString);
SqlCommand com = new SqlCommand("ADD_TO_BEFORE_PATH_SP", con);
com.Parameters.AddWithValue("#fname", fname_tb.Text);
com.Parameters.AddWithValue("#lname", lname_tb.Text);
com.CommandType = CommandType.StoredProcedure;
try
{
con.Open();
com.ExecuteNonQuery();
}
catch (Exception)
{
throw;
}
finally
{
if (con.State == ConnectionState.Open)
con.Close();
}
I am trying to update a particular column of a SQL Server table using my aspx page on button click event. My code is:
if (AutoMan.Text == "Auto Mode")
{
var x = "1";
var y = DateTime.Now.ToString();
var z = "1";
using (SqlConnection con = new SqlConnection(#"Data Source=localhost.\SQLEXPRESS;Initial Catalog=MCAS;Integrated Security=SSPI;"))
{
con.Open();
try
{
using (SqlCommand cmd = new SqlCommand("UPDATE AutoManLog SET AutoMan = #data, Time = #data1", con))
{
cmd.Parameters.AddWithValue("#data1", y);
cmd.Parameters.AddWithValue("#data", x);
cmd.ExecuteNonQuery();
}
}
catch (Exception Ex)
{
Response.Write("Unable To Save Data. Error - " + Ex.Message);
}
con.Close();
}
Data in the database is not updating. I Can't see any error messages.
in this query:
"UPDATE AutoManLog SET AutoMan = #data, Time = #data1"
Time is a preserved name for sql server; so use it as [Time] will be solve the problem,
if there isn't another problem exist.
I copy-pasted your code and it works just as is; your parameters are correct, and your statement is correct.
Your possible issues are:
AutoMan.Text does not equal "Auto Man" -- make sure they are equal
Any error occurring (database connection, table doesn't exist, etc.), but something is obstructing your Response.Write output, not making you able to see the output -- take out the try-catch, and let the debugger catch errors so you can trace it better
I'm trying to upgrade the db from users' input, but it doesn't work...
I'm using this:
protected void Button1_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(strcon);
SqlCommand cmd = new SqlCommand();
SqlCommand ncmd = new SqlCommand("Update Utenti Set Nome = #vnome where [Indirizzo E-Mail]=#vem", con);
ncmd.Parameters.AddWithValue("#vem", Session["[Indirizzo E-Mail]"].ToString());
ncmd.Parameters.AddWithValue("#vnome", TextBox2.Text);
ncmd.Connection = con;
con.Open();
ncmd.ExecuteNonQuery();
con.Close();
Label2.Text = "Dati aggiornati con successo!";
Response.Redirect("~/ModificaDati.aspx");
}
When I click on the button it show me the Label2 text, but in the database the "Nome" is not changed, why?
Thanks before for the answers ^^
I would change your method as below
if (Session["[Indirizzo E-Mail]"] != null &&
!string.IsNullOrEmpty(Session["[Indirizzo E-Mail]"].ToString()) &&
!string.IsNullOrEmpty(TextBox2.Text))
{
string vem = Session["[Indirizzo E-Mail]"].ToString();
using (var con = new SqlConnection(strcon))
using (var ncmd = new SqlCommand("Update Utenti Set Nome = #vnome where [Indirizzo E-Mail]=#vem", con))
{
con.Open();
ncmd.Parameters.AddWithValue("#vem", vem);
ncmd.Parameters.AddWithValue("#vnome", TextBox2.Text);
int rows = ncmd.ExecuteNonQuery();
Label2.Text = rows + " Dati aggiornati con successo!";
}
}
Response.Redirect("~/ModificaDati.aspx");
Added input validation, session values can be null, better to check before you update database
when you create SqlCommand you can give the connection, no need to set it again
make sure your SQL is valid
use using statements for disposable objects like SqlConnection, SqlCommand
Your code looks ok. Just make sure you check if SQL is correct as Damith already suggested.
Another thing I’s recommend is additionally validating your parameters for data type correctness before executing the query.
Using this approach you’ll probably avoid a lot of unnecessary exceptions and also be able to provide more user friendly messages. Of course this only applies if user input is non text type
//Data Type verification
DateTime tmp;
if (!DateTime.TryParse(Label2.Text.Trim(), out tmp))
{
//Show error message that this is not a correct data type
}
Open your connection first
con.Open();
ncmd.Connection = con;
Hope it helps