C# MySQL Parameterized update returning nothing - c#

Whenever I try to update my database, the result ends up being 0.
If I do it in HeidiSQL, it updates just fine, so I know it's not the query.
I have my suspicion that it has to do with the parameters, but I'm unsure regarding that.
I tried with both # and ?, but neither have worked.
MySqlCommand Command = new MySqlCommand("UPDATE `users` SET `cash`=#Cash,
`distance_driven`=#DistanceDriven, `jobs_done`=#JobsDone,
`job_rank`=#JobRank WHERE `username`='#Username';"
, Connection);
Command.Parameters.AddWithValue("#Cash", Cash);
Command.Parameters.AddWithValue("#DistanceDriven", DistanceDriven);
Command.Parameters.AddWithValue("#JobsDone", JobsDone);
Command.Parameters.AddWithValue("#JobRank", JobRank);
Command.Parameters.AddWithValue("#Username", UName);
int result = Command.ExecuteNonQuery(); // result should be 1
Console.WriteLine(result); // ends up being 0
The connection opens fine, but I have no idea why it won't execute the query with the parameters.
Here is the function that requires this update:
public void UpdateUserInfo(object sender, ElapsedEventArgs evt, string uUName)
{
bool cont = false;
Console.WriteLine("UUI 1: " + evt.SignalTime); // gets here fine
try
{
Console.WriteLine("UUI 2: " + evt.SignalTime); // gets here fine
Database database = new Database();
database.Connect();
if (database.UpdateUserData(uUName, TotalCashWallet, TotalDistanceDriven, JobsDone, JobRank))
{
cont = true;
Console.WriteLine("UUI 3: " + evt.SignalTime); // doesn't get here
}
if (cont == true)
{
cont = false;
Console.WriteLine("UUI 4: " + evt.SignalTime);
if (database.UpdateUserBank(uUName, BankInfo.Money, BankInfo.BonusPercentage, BankInfo.BonusLevel))
{
UserInfoUpdated = true;
Console.WriteLine("UUI 5: " + evt.SignalTime);
UserInfoUpdatedTimer.Enabled = true;
return;
}
}
UserInfoUpdated = false;
return;
}
catch (Exception e)
{
Console.WriteLine("UUI 6: " + evt.SignalTime);
Console.WriteLine(e.Message);
ErrorHandler.WriteToLog(e.StackTrace);
ErrorHandler.WriteToLog(e.Message);
ErrorHandler.WriteToLog("------------------------------");
}
return;
}
It doesn't get to the catch part, so it won't log anything.
I tried with both Exception and MysqlException, but it doesn't catch an error.
Doing it the unsafe way works
MySqlCommand Command = new MySqlCommand("
UPDATE `users`
SET `cash`=" + Cash + ",
`distance_driven`=" + DistanceDriven + ",
`jobs_done`=" + JobsDone + ",
`job_rank`=" + JobRank + "
WHERE `username`='" + UName + "';"
, Connection);

You don't need the single quotes around string parameters. Use this query instead:
string query = #"
UPDATE `users` SET
`cash`=#Cash,
`distance_driven`=#DistanceDriven,
`jobs_done`=#JobsDone,
`job_rank`=#JobRank
WHERE
`username`=#Username"
MySqlCommand command = new MySqlCommand(query, Connection);

Related

Update sql database from datagridview in c#

I'm new here but I need some help. I need to update a SQL Server database from C# with Windows Forms, but I'm having problems. I looked it up but still can't find the right answer. I need to do insert and update by pressing a button for changing or filling the database from the datagridview. I've created a separate function for both I am using this code;
private void InsertPositionen()
{
string qry = "";
SqlCommand insert = new SqlCommand(qry, con);
try
{
for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
{
qry = "INSERT INTO BelegePositionen (BelID, BelPosId, Artikelnummer, Menge, Preis) VALUES( " + dataGridView1.Rows[i].Cells["BelID"] + ", "
+ dataGridView1.Rows[i].Cells["BelPosId"] + ", "
+ dataGridView1.Rows[i].Cells["Artikelnummer"] + ", "
+ dataGridView1.Rows[i].Cells["Menge"] + ", "
+ dataGridView1.Rows[i].Cells["Preis"];
}
insert.ExecuteNonQuery();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void UpdatePositionen()
{
string updt = "";
SqlCommand update = new SqlCommand(updt, con);
try
{
for (int i = 0; i < dataGridView1.Rows.Count -1; i++)
{
updt = "UPDATE BelegePositionen SET BelID = "
+ dataGridView1.Rows[i].Cells["BelID"] +
", BelPosID = "
+ dataGridView1.Rows[i].Cells["BelPosID"] +
", Atrikelnummer = "
+ dataGridView1.Rows[i].Cells["Artikelnummer"] +
", Menge = "
+ dataGridView1.Rows[i].Cells["Menge"] +
", Preis = "
+ dataGridView1.Rows[i].Cells["Preis"];
}
update.ExecuteNonQuery();
con.Close();
MessageBox.Show("Done!");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
You should really NOT do your SQL stuff like this!! This leaves your code wide open for SQL injection vulnerabilities! Stop that - right now!
Instead - use parametrized queries - like this:
private void InsertPositionen()
{
string qry = "INSERT INTO BelegePositionen (BelID, BelPosId, Artikelnummer, Menge, Preis) " +
"VALUES(#BelId, #BelPosId, #ArtNr, #Menge, #Preis);";
SqlCommand insert = new SqlCommand(qry, con);
// define the parameters
insert.Parameters.Add("#BelId", SqlDbType.Int);
insert.Parameters.Add("#BelPosId", SqlDbType.Int);
insert.Parameters.Add("#ArtNr", SqlDbType.Int); // maybe this is a string?
insert.Parameters.Add("#Menge", SqlDbType.Int);
insert.Parameters.Add("#Preis", SqlDbType.Decimal, 20, 4);
try
{
// in the loop, only *set* the parameter's values
for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
{
insert.Parameters["#BelId"].Value = 1;
insert.Parameters["#BelPosId"].Value = 2;
insert.Parameters["#ArtNr"].Value = 3;
insert.Parameters["#Menge"].Value = 4;
insert.Parameters["#Preis"].Value = 99.95;
insert.ExecuteNonQuery();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Your Question is quite vague as you state you are having problems, but not quite sure what problems you are having. It will help if you can describe what problems you are having.
In addition to what #marc_c said about sql injection, I can't see how you manage your connection to the database.
From the code it looks like you could run into a situation where you are leaving connection strings open, or not opening them at all.
using the using(...) { } will close the connections when you are done with it.
private void InsertPositionen()
{
//using the using statement you will insure that the connection is closed and resources released
using (SqlConnection connection = new SqlConnection(Properties.Settings.Default.db))
{
string cmd = "INSERT INTO BelegePositionen (BelID, BelPosId, Artikelnummer, Menge, Preis) " +
"VALUES(#BelId, #BelPosId, #ArtNr, #Menge, #Preis);";
//using the using statement will ensure any reasources are released when exiting the code block
using (SqlCommand insert = new SqlCommand(cmd, connection))
{
// define the parameters
insert.Parameters.Add("#BelId", SqlDbType.Int);
insert.Parameters.Add("#BelPosId", SqlDbType.Int);
insert.Parameters.Add("#ArtNr", SqlDbType.Int); // maybe this is a string?
insert.Parameters.Add("#Menge", SqlDbType.Int);
insert.Parameters.Add("#Preis", SqlDbType.Decimal, 20, "4");
try
{
//open the connection
insert.Connection.Open();
// in the loop, only *set* the parameter's values
for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
{
insert.Parameters["#BelId"].Value = dataGridView1.Rows[i].Cells["BelID"];
insert.Parameters["#BelPosId"].Value = dataGridView1.Rows[i].Cells["BelPosId"];
insert.Parameters["#ArtNr"].Value = dataGridView1.Rows[i].Cells["Artikelnummer"];
insert.Parameters["#Menge"].Value = dataGridView1.Rows[i].Cells["Menge"];
insert.Parameters["#Preis"].Value = dataGridView1.Rows[i].Cells["Preis"];
insert.ExecuteNonQuery();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
MessageBox.Show("Done!");
}
}
}
}

OleDb Update requires Insert Command?

I try to updata a single row, chosen by it ID. But what I got at best is an additional row instead of an updated one.
I made several attempts. Now I got a System.InvalidOperationException claiming that a valid InsertCommand is necessary for an update, if a DataRow listing will get a new row.
To me it is the same again: Why insert? I want to update.
Can anybody give me a hint?
This is my related code:
string selectQuery = $"SELECT * FROM Records";
string updateQuery = $"UPDATE Records SET AnyContent = #AnyContent WHERE [ID] = #ID";
OleDbDataAdapter adapter = null;
OleDbCommand cmd = null;
try
{
adapter = new OleDbDataAdapter(selectQuery, ConnectionString);
cmd = new OleDbCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = updateQuery;
cmd.Parameters.AddWithValue ("#AnyContent", "066066");
cmd.Parameters.AddWithValue("#ID", 2);
try
{
adapter.UpdateCommand = cmd;
nbRowsChanged = adapter.Update(content);
}
finally
{
adapter?.Close();
cmd?.Close();
}
}
catch (OleDbException e)
{
logText += "...Database Exception:\n\n" + e.Message + "\n\n";
isSuccess = false;
}
if (0 < nbRowsChanged)
{
logText += ".... Success: Updated <" + nbRowsChanged.ToString() + "> rows.\n";
isSuccess = true;
}
<<< Update >>>
Originally I tried it with an OleDbCommandBuilder before. But CommandBuilder created an update command, which seems to me like an insert command. This is why I tried it without CommandBuilder above. But inserting seems to follow me.
This is my old code, which is closer to where I want to get as it uses a DataTable instead of parameters:
string selectQuery = $"SELECT * FROM Records WHERE [ID] = ?";
OleDbConnection con = null;
OleDbDataAdapter adapter = null;
OleDbCommandBuilder builder = null;
try
{
adapter = new OleDbDataAdapter();
con = new OleDbConnection(ConnectionString);
adapter.SelectCommand = new OleDbCommand(selectQuery, con);
builder = new OleDbCommandBuilder(adapter);
try
{
con.Open();
nbRowsChanged = adapter.Update(content);
logText += "....InsertCommand: " + builder.GetInsertCommand().CommandText + "\n"; // Just to debug
logText += "....UpdateCommand: " + builder.GetUpdateCommand().CommandText + "\n"; // Just to debug
}
finally
{
con?.Close();
adapter?.Dispose();
}
}
catch (OleDbException e)
{
logText += "...Database Exception:\n\n" + e.Message + "\n\n";
isSuccess = false;
}
if (0 < nbRowsChanged)
{
logText += ".... Success: Updated <" + nbRowsChanged.ToString() + "> rows.\n";
isSuccess = true;
}
logText += tmpText ;
logText += "...Database: Access disposed.\n";
return isSuccess;
And this is the related trace:
LogText:
...Database: Trying to update <1> number of rows in table <Records>
....InsertCommand: INSERT INTO Records (AnyContent) VALUES (?)
....UpdateCommand: UPDATE Records SET AnyContent = ? WHERE ((ID = ?) AND ((? = 1 AND AnyContent IS NULL) OR (AnyContent = ?)))
.... Success: Updated <1> rows.
...Database: Access disposed.
NbRows Before: 5
NbRows After: 6

Executing a query with no search term causes System.StackOverflow Exception in System.Runtime.Serialization.dll

I 'm dealing with a query which results in above mentioned error when called with no or limited search string.
The table is 30k records big and when the query is fired with no search string I would expect the database to return all records and have Visual Studio put them in a table (ASP.net), however, if the query is fired like above the StackOverflow error is returned :(
If I fire the query with a more specific search string the script seems to work normal and results are being returned as expected.
I have been googling and all seems to point to an infinite loop or recursion but returning records make me believe it might be another problem.
The query:
SqlConnection conn = new SqlConnection(_cstring);
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
conn.Open();
SqlDataReader dr;
if (mode == "zoek_met_zoekterm")
{
cmd.CommandText = "select W1.id, W1.soort_brief, W1.omschrijving, W1.referentie, W1.url, W1.factuur, W3.naam, W3.klantnummer, W4.omschrijving AS w4_omschr, W4.referentie AS w4_ref, substring(W1.referentie,6,2) as w1_jaar, W1.parent AS w1_parent from brief W1 left join brief W4 on W1.parent = W4.id join klant W3 on W3.klantnummer = W1.klantnummer where W1.referentie in (select referentie from brief where substring(referentie,6,2) = #jaar) and (W3.klantnummer like #zoekterm or W1.referentie like #zoekterm or W1.omschrijving like #zoekterm or W3.naam like #zoekterm or W4.omschrijving like #zoekterm) order by W1.id";
cmd.Parameters.Clear();
cmd.Parameters.Add("#zoekterm", SqlDbType.VarChar).Value = "%" + (string)parameters["zoekterm"] + "%";
string jaar = parameters["jaar"].ToString();
jaar = jaar.Substring(2, 2);
cmd.Parameters.Add("#jaar", SqlDbType.VarChar).Value = jaar;//(Int32)parameters["jaar"];
base.LogQuery(cmd);
dr = cmd.ExecuteReader();
while (dr.Read())
{
CBrief brief = new CBrief();
brief.Id = dr.GetInt32(0);
brief.SoortBrief = (Enums.SoortBrief)dr.GetInt32(1);
brief.Omschrijving = Functies.Decrypt(dr.GetString(2), EncryptData);
brief.Referentie = Functies.Decrypt(dr.GetString(3), EncryptData);
brief.Url = Functies.Decrypt(dr.GetString(4), EncryptData);
brief.Factuur = (Enums.SoortDocument)dr.GetInt32(5);
brief.Klantnummer = dr.GetInt32(7);
if (dr.GetString(2).Length == 0)
{
if (!dr.IsDBNull(9) && !dr.IsDBNull(8))
brief.Omschrijving = dr.GetString(9) + " " + dr.GetString(8);
}
ret_value.Add(brief);
}
dr.Close();
dr.Dispose();
}
And the function that calls the query:
public List<CBrief> GetBriefOverzicht(string zoekterm, int jaar)
{
Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("zoekterm", zoekterm);
parameters.Add("jaar", jaar);
if (zoekterm.Length == 0)
{
return _dal.brief_search(parameters, "geen_invoer");
}
return _dal.brief_search(parameters, "zoek_met_zoekterm");
}
And last but not least the function that builds the table to display in the web application:
protected void Bzoeken_Click(object sender, EventArgs e)
{
string zoekterm = TBzoekterm.Text;
DateTime nu = DateTime.Now;
int jaar = nu.Year;
List<CBrief> brieven = br_rbs.GetBriefOverzichtWijzigen(zoekterm);
StringBuilder overzicht = new StringBuilder("<table class=\"tabel-beheer-1\">");
foreach (CBrief b in brieven)
{
List<CBijlage> bijlagen = new List<CBijlage>();
CKlant k = sec.GetKlant(b.Klantnummer);
string klantnaam = k.Naam;
string richting = "";
if (b.OmschrijvingAanwezig == true)
{
bijlagen = br_rbs.GetBijlagenBrieven(b.Id);
}
if (b.SoortBrief == Enums.SoortBrief.Inkomend) richting = "van: "; else richting = "naar: ";
// MG10082017 Ik heb hier twee icoontjes in elkaar geflanst om te testen. Deze moeten nog aangepast worden zodat ze in het geheeel passen.
overzicht.AppendLine("<tr><td><img src=\"/images/bg/document.jpg\" alt=\"open document\"></td><td><img src=\"/images/bg/detail.jpg\" alt=\"details\"></td><td><b>" + b.Referentie + "</b></td><td><i>" + b.SoortBrief.ToString() + " " + richting + "</i> " + klantnaam + "</td><td><b> " + b.Factuur.ToString() + ":</b> " + b.Omschrijving /*+"</td><td>"*/);
if (bijlagen.Count > 0)
{
foreach (CBijlage bijl in bijlagen)
{
overzicht.AppendLine("</br> " + bijl.Naam + "");
}
}
}
overzicht.AppendLine("</td></tr></table>");
Loverzicht.Text = overzicht.ToString();
}
The error usually points to: System.Web.dll or w3wp.exe (when not ran in debug mode). If my assumption is wrong and it seems to be an infinite loop or recursion, how am I going to find this?
The query works flawless in MS-SQL management console.
The Problem is not an infinite loop!
The Problem lies in the UI.
You can't display 30k units at once without a StackOverflow-Exception.
You should call pages of maybe 20 or 30 units at once with an pageIndex.
This way, your application will perform better and avoid such errors.

using one button to insert and update different db tables

I am using the same button "Save" to update a table called AnalysisExperiments and also to insert data into a table called "Analysis". however the update is not working. Here is the code:
#region Insert Data into Analysis Table
if (checkIfRepeatedJobNumber(tbJobNumber.Text.Trim()))
{
MessageBox.Show("Job Number is already exist.", "Repeated Data");
return;
}
string query = "insert into Analysis (ID, WellName, EstimatedStartDate, SOWComments, ProgressComments, Field, FocalPoint, StudyCompleted, Company, ReservoirPressure, ReservoirTemp, SelectedSamples) " +
"values (#ID, #WellName, #SamplingDate, #SOWComments, #ProgressComments, #Field, #FocalPoint, #StudyCompleted, #Company, #ReservoirPressure, #ReservoirTemp, #SelectedSamples)";
OleDbCommand cmd = new OleDbCommand(query, conn);
cmd.Parameters.AddWithValue("#ID", tbJobNumber.Text);
cmd.Parameters.AddWithValue("#WellName", tbWellName.Text);
cmd.Parameters.AddWithValue("#SamplingDate", dtpSamplingDate.Text);
cmd.Parameters.AddWithValue("#SOWComments", tbSOW_Comments.Text);
cmd.Parameters.AddWithValue("#ProgressComments", tbProgressComments.Text);
cmd.Parameters.AddWithValue("#Field", tbFieldName.Text);
cmd.Parameters.AddWithValue("#FocalPoint", tbFocalName.Text);
if (radYes.Checked)
cmd.Parameters.AddWithValue("#StudyCompleted", "Yes");
else
cmd.Parameters.AddWithValue("#StudyCompleted", "No");
cmd.Parameters.AddWithValue("#Company", tbCompany.Text);
cmd.Parameters.AddWithValue("#ReservoirPressure", tbReservoirPressure.Text);
cmd.Parameters.AddWithValue("#ReservoirTemp", tbReservoirTemp.Text);
cmd.Parameters.AddWithValue("##SelectedSamples", tbSelectedSamples.Text);
try
{
conn.Open();
int j = cmd.ExecuteNonQuery();
if (j == 1)
{
MessageBox.Show("Done");
this.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
conn.Close();
}
#endregion
#region update analysis Exp but still no working
#region Update database
try
{ int k = 0;
OleDbDataAdapter da;
da = new OleDbDataAdapter("select* from [AnalysisExperiments]", conn);
string ExpQuery = "update AnalysisExperiments set SampleNumber = #SampleNumber, Status = #Status where ID = '" + tbJobNumber.Text + "' and Experiment = '";
foreach (DataGridViewRow row in dgvExperiments.Rows)
{
ExpQuery += row.Cells["Experiment"].Value.ToString() + "'";
OleDbCommand updateCommand = new OleDbCommand(ExpQuery, conn);
updateCommand.Parameters.Add("#SampleNumber", OleDbType.VarWChar);
MessageBox.Show(row.Cells["SampleNumber"].Value.ToString() + " | " + row.Cells["Status"].Value.ToString() + " | " + row.Cells["Experiment"].Value.ToString());
updateCommand.Parameters["#SampleNumber"].Value = row.Cells["SampleNumber"].Value.ToString();
updateCommand.Parameters.Add("#Status", OleDbType.Boolean);
updateCommand.Parameters["#Status"].Value = row.Cells["Status"].Value;
da.UpdateCommand = updateCommand;
conn.Open();
k = da.UpdateCommand.ExecuteNonQuery();
conn.Close();
}
if (k == 1)
MessageBox.Show("Done");
else
{
MessageBox.Show("Nothing Updated!");
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
#endregion
#endregion
knowing that the compiler skips the loop in the update region.
At the second loop the query syntax becomes invalid cause the += that concatenates the previous text with the new one
Dim newQuery = ExQuery + row.Cells["Experiment"].Value.ToString() + "'";
And then use the new string for the ExecuteNonQuery.
Still this approach has many problems. You should separate this code in different methods and use parameters also for the last value
Have you tried to debug the foreach line to see if there are any rows in your dgvExperiments and if they are of type (or subtype of) DataGridViewRow ?

C# Variable scope in switch statement

I have a function that begins with this:
void RecordLoadPosition()
{
OdbcCommand command;
if (_hasPlantGenie)
{
command = new OdbcCommand();
string query;
switch (ItemType)
{
case ItemTypeEnum.COIL:
// We're only going to add records to the coils_pg table when the coil gets moved. After
// a record is added, we'll update it.
command = new OdbcCommand("select * from coils_pg where coil_id = " + _itemName, _db);
When I compile this, I do not get an error on the first line in the if block, but I get errors complaining that I cannot use "command" before it is declared inside the case block. I don't understand why the declaration at the top of the function is not available inside the case block.
But OK. If it's not visible in the case block, I can just declare it. I changed the first statement in the case block to "OdbcCommand command...". Now I get an error complaining that I can't declare a variable that is already declared in a parent block! I can't win either way!
What is happening here?
Of course, I can just use different OdbcCommand objects, and that's what I'll do for now, but I'd like to understand this.
=============================================
It does appear that something is missing in my original code sample, but I have no idea what. Here is a small function that should have shown the same error, but did not:
void ScopeTest()
{
OdbcCommand command = null;
if (_hasPlantGenie)
{
command = new OdbcCommand();
switch (ItemType)
{
case ItemTypeEnum.COIL:
// We're only going to add records to the coils_pg table when the coil gets moved. After
// a record is added, we'll update it.
command = new OdbcCommand();
break;
}
}
}
==============================================
And, because people asked for it, here is the complete original function (including the extra creation of an OdbcCommand object at the top of the if block merely to demonstrate that it does not throw an error:
void RecordLoadPosition()
{
OdbcCommand command = null;
if (_hasPlantGenie)
{
command = new OdbcCommand();
string query;
switch (ItemType)
{
case ItemTypeEnum.COIL:
// We're only going to add records to the coils_pg table when the coil gets moved. After
// a record is added, we'll update it.
command = new OdbcCommand("select * from coils_pg where coil_id = " + _itemName, _db);
OdbcDataReader reader = command.ExecuteReader();
if (reader.Read())
{
query = "update plant_genie.coils_pg set x_coordinate = " +
XPosCurrent.ToString() +
", y_coordinate = " +
YPosCurrent.ToString() +
" where coil_id = '" +
_itemName + "'";
reader.Close();
command.CommandText = query;
command.ExecuteNonQuery();
}
else
{
query = "insert into plant_genie.coils_pg(coil_id, x_coordinate, y_coordinate) values (" +
XPosCurrent.ToString() + YPosCurrent.ToString() +
"'" + _itemName + "')";
reader.Close();
command.CommandText = query;
command.ExecuteNonQuery();
}
break;
case ItemTypeEnum.INNER_COVER:
// The inner_cover_pg table will be pre-built. We can assume that it has records for
// each inner cover.
query = "select set_inner_cover_down(" +
XPosCurrent.ToString() +
", " +
YPosCurrent.ToString() +
", '" +
_itemName +
"')";
OdbcCommand command = new OdbcCommand(query, _db);
command.ExecuteNonQuery();
// See if the cover has been set down in a storage location. If it has
break;
}
}
}
Inside your case ItemTypeEnum.INNER_COVER: condition, you have:
OdbcCommand command = new OdbcCommand(query, _db);
You're redeclaring it, when you should just be assigning it like you are in the case ItemTypeEnum.COIL: branch. Replace that line with this:
command = new OdbcCommand(query, _db);

Categories

Resources