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();
Related
I have created a program (for school) that has create account, manage account (update and delete), and delete account. All functions work except for Update and I am not sure why. There's no error whatsoever, it just does nothing. Below is the code:
private void btnUpdate_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["myCon"].ConnectionString);
con.Open();
using (SqlCommand cmd = new SqlCommand("UPDATE Inventory SET ItemID=#ItemID, ItemName=#ItemName, ItemType=#ItemType, Quantity=#Quantity,WarehouseLocation=#WarehouseLocation,QuadrantNumber=#QuadrantNumber,BinNumber=#BinNumber,DateUpdated=#DateUpdated" +
" WHERE ItemID= '" + txtItemID.Text + "'", con))
{
if (txtItemID.Text == "#ItemID")
{
cmd.Parameters.AddWithValue("#ItemName", txtItemName.Text);
cmd.Parameters.AddWithValue("#ItemType", cmbType.Text);
cmd.Parameters.AddWithValue("#Quantity", udQuantity.Text);
cmd.Parameters.AddWithValue("#WarehouseLocation", cmbWarehouse.Text);
cmd.Parameters.AddWithValue("#QuadrantNumber", cmbQuadrant.Text);
cmd.Parameters.AddWithValue("#BinNumber", cmbBin.Text);
cmd.Parameters.AddWithValue("#DateUpdated", Convert.ToString(DateTime.Now));
cmd.ExecuteNonQuery();
con.Close();
MessageBox.Show("Item Updated!");
}
}
}
This answer is based in assumption you already have this item in your DB and you just need to update it. I'll separate the answer in three steps:
First step: I assume your primary_key is the ItemID, so you shouldn't really update it as you're doing here:
UPDATE Inventory SET ItemID=#ItemID,...
You should just remove the ItemID = #ItemID, part, as we don't want to update it.
Second step: Now, this piece of code looks incorrect:
if (txtItemID.Text == "#ItemID")
It will try to match the txtItemID.Text with the string "#ItemID", which I believe it is not your goal, since I can understand it is your ID - It would be always false.
You should just remove this if.
Third step: You also need to change your where clause to have your ItemID as parameter, as below:
" WHERE ItemID=#ItemID", con))
Then add it to your parameters:
cmd.Parameters.AddWithValue("#ItemID", txtItemID.Text);
You should be good with these changes.
Another thing you could do is to always debug your application when you're struggling to understand a problem. It helps a lot!
I have a program which is supposed to open, edit, create and save access databases. For saving I copy an empty database with just the tables (just to avoid going through the hassle of creating every table and column etc) and try to fill it with values via the TableAdapterManager.UpdateAll method.
string _TemplateConnectString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};";
_connection = new OleDbConnection(string.Format(_TemplateConnectString, dlg.FileName));
_connection.Open();
DataSet1TableAdapters.TableAdapterManager tam=new TableAdapterManager();
tam.Connection = _connection;
try
{
tam.UpdateAll(dataset);
}
catch (System.Exception ex)
{
MessageBox.Show("Update failed");
}
It finishes with no exceptions but the values don't get inserted into the new database.
Also as far as I know the UpdateAll method only updates modified row so if I open some db and it inserts it's rows, it will not take them into account even though there are not in the database that I am trying to fill.
I have also tried filling the database with the ADODB and ADOX extensions but all the solutions I found with those was a lot of hardcoding and no regards for hierarchy, keys, etc.
Is there a way to force insert everything in the new database?
Is your template database in the Visual Studio project directory? It might have something to do with Visual Studio copying the database to the bin/debug or bin/release folder...
Try to use the right Data source database name, here an
example with an excel file:
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=c:\somepath\ExcelFile.xls;" & _
"Extended Properties=""Excel 8.0;HDR=Yes;"";"
A clumsy solution but it works. I iterate the tables of the dataset and save the via an sql string generator like this:
void SaveTable(DataTable dt)
{
string[] inserts;
try
{
inserts = SqlHelper.GenerateInserts(dt, null, null, null);
foreach (string s in inserts)
{
OleDbCommand cmd = new OleDbCommand();
cmd.CommandText = s;
cmd.Connection = _connection;
int n = cmd.ExecuteNonQuery();
}
}
catch (Exception e)
{
SaveOk = false;
}
}
I found the SqlHelper somewhere on this site, but completely lost where, unforunately. So here is the pastebin with it https://pastebin.com/iCMVuYyu
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.
public TransImport()
{
ConnString = ConfigurationManager.ConnectionStrings["Connection"].ConnectionString;
SqlConnection conn_new;
SqlCommand command_serial_new;
SqlConnection conn;
SqlCommand command_serial;
SqlTransaction InsertUpdateSerialNumbers;
conn = new SqlConnection(ConnString);
command_serial = conn.CreateCommand();
conn_new = new SqlConnection(ConnString);
command_serial_new = conn_new.CreateCommand();
command_serial_new.CommandText = "SELECT 1 FROM YSL00 WHERE SERLNMBR = #slnr";
var p = new SqlParameter("#slnr", SqlDbType.NVarChar, 50);
command_serial_new.Parameters.Add(p);
//Here you will start reading flat file to get serialnumber.
InsertUpdateSerialNumbers = conn.BeginTransaction();
while (!headerFileReader.EndOfStream)
{
headerRow = headerFileReader.ReadLine();
if (CheckSerialNumber(headerFields[0].Trim()))
DisplayMessage("Good serialnumber"); //this function is not copied here.
}
InsertUpdateSerialNumbers.Commit();
}
private Boolean CheckSerialNumber(string SerialNumber)
{
command_serial_new.Parameters["#slnr"].Value = SerialNumber;
try
{
var itExists = Convert.ToInt32(command_serial_new.ExecuteScalar()) > 0;
if (!itExists)
{
command_serial.Transaction = InsertUpdateSerialNumbers;
command_serial.CommandText = "INSERT INTO YSL00([Manifest_Number],[PONUMBER],[ITEMNMBR],[SERLNMBR]"
+ "VALUES ('" + Manifest + "','" + PONr + "','" + itemNumber + "','" + serialNr + "')";
var insertStatus = command_serial.ExecuteNonQuery();
return true;
}
}
catch (Exception ex)
{
LogException(ex, "Error in CheckSerialNumber =>"+ command_serial_new.CommandText.ToString());
}
return false;
}
I get error "Timeout expired. The timeout period elapsed prior to completion of the operation or server is not responding".
The CheckSerialNumber function also does an insert to YSL00 (the same table where I had executescalar. See code above).
As I mentioned earlier there are 1000s of line in a flat file that I read and update YSL000 table.
Note that I have two separate sqlcommands and also two separate connections to handle this. Reason is with sqltransaction it doesn't let me to query on the same table. I think timeout may be happening because of this?
Thanks for reading. Please suggest
Update 1: Since I have not pasted entire code, I want to mention that dispose is done using below code in the program.
if (conn != null)
{
conn.Close();
conn.Dispose();
}
if (conn_new != null)
{
conn_new.Close();
conn_new.Dispose();
}
you can increase the time out of your SqlConnection object.
you can do this with your ConnString:
string connStr = "Data Source=(local);Initial Catalog=AdventureWorks;Integrated
Security=SSPI;Connection Timeout=300";
I think default isolation level - read commited - is preventing your 'CheckSerialNumber' method from being effective. Command_serial_new will not take into consideration rows inserted in your loop - this might lead to some troubles. To be honest I would also look for some deadlock. Perhaps command_serial_new is actually completely blocked by the other transaction.
To start off:
Set command_serial_new query as:
SELECT 1 FROM YSL00 WITH (NOLOCK) WHERE SERLNMBR = #slnr
Think about using lower isolation level to query inserted rows as well (set it to read uncommited).
Close your connections and transactions.
Use just one SqlConnection - you don't need two of them.
Many of the objects you are using implement IDisposable, and you should be wrapping them with using statements. Without these using statements, .NET won't necessarily get rid of your objects until an undetermined time when the garbage collector runs, and could block subsequent queries if it's still holding a transaction open somewhere.
So for example, you'll need to wrap your connections with using statements:
using (conn_new = new SqlConnection(ConnString)) {
...
If I am not mistaken you need to merge the file content with the table content.
For this purpose I would recommend you
Copy the file content in to a temporary table (see temporary tables and BulkInsert)
Use command MERGE (http://msdn.microsoft.com/en-us/library/bb510625.aspx) to merge the temporary table content with the original table
I'm writing a music player application using WPF (C#). As part of its functionality, I'm populating a music library, where I'm storing the Title and Path to an mp3 file. The user gets to select a root folder for his music library and then the contents are populated in a "Songs" table. This is the code that I've written:
private void Populate_Click(object sender, RoutedEventArgs e)
{
// Folder browser
FolderBrowserDialog dlg = new FolderBrowserDialog();
dlg.ShowDialog();
string DirectoryPath = System.IO.Path.GetDirectoryName(dlg.SelectedPath);
// Get the data directory
string[] A = Directory.GetFiles(DirectoryPath, "*.mp3", SearchOption.AllDirectories);
string[] fName = new string[A.Count()];
// Initialize connection
string connstr = "Data Source=.\\SQLEXPRESS;AttachDbFilename=|DataDirectory|\\Database.mdf;Integrated Security=True;User Instance=True";
SqlConnection conn = new SqlConnection(connstr);
conn.Open();
// Create the SqlCommand
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "InsertSongs";
// Create the parameters and execute the command
for (int i = 0; i < A.Count(); i++)
{
fName[i] = System.IO.Path.GetFileName(A[i]);
cmd.Parameters.AddWithValue("#Title", fName[i]);
cmd.Parameters.AddWithValue("#Path", A[i]);
try
{
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
System.Windows.MessageBox.Show("Error: " + ex.Message);
}
finally
{
listBox1.Items.Add(A[i]);
listBox2.Items.Add(fName[i]);
cmd.Parameters.Clear();
}
}
// Close the connection
cmd.Dispose();
conn.Close();
conn.Dispose();
}
The code for the stored procedure is simple -
ALTER PROCEDURE dbo.InsertSongs
(
#Title nvarchar(50),
#Path nvarchar(50)
)
AS
INSERT INTO Songs(Title, Path) VALUES(#Title, #Path)
Now, when I execute the program, there is no error message thrown (the file names and directory names have size less than 50). However, at the end of execution, no value is inserted in the Songs table.
The Songs table is described as below:
ID int
Title nvarchar(50)
Path nvarchar(50)
I'm not sure where I went wrong: I have also tried using SqlParameter and then defining the type of parameter as NVARCHAR with size 50, but to no avail. May I kindly request you to assist me here? Many thanks in advance.
The whole User Instance and AttachDbFileName= approach is flawed - at best! Visual Studio will be copying around the .mdf file and most likely, your INSERT works just fine - but you're just looking at the wrong .mdf file in the end!
If you want to stick with this approach, then try putting a breakpoint on the myConnection.Close() call - and then inspect the .mdf file with SQL Server Mgmt Studio Express - I'm almost certain your data is there.
The real solution in my opinion would be to
install SQL Server Express (and you've already done that anyway)
install SQL Server Management Studio Express
create your database in SSMS Express, give it a logical name (e.g. SongsDatabase)
connect to it using its logical database name (given when you create it on the server) - and don't mess around with physical database files and user instances. In that case, your connection string would be something like:
Data Source=.\\SQLEXPRESS;Database=SongsDatabase;Integrated Security=True
and everything else is exactly the same as before...