SqlCommand AddWithValue and if statements issue with gridview - c#

I am trying to build a web form that uses SQL queries to help populate various dropdowns and display results in gridviews, the issue i'm having at the moment is getting the user input to replace varibles in the SQL query.
My query is as follows:
SELECT TOP 50
'Select' AS 'Select',
id_ref AS 'Number',
created_date AS 'Date Created',
address 'Address',
category AS 'Category',
borough
FROM Events
WHERE location_address LIKE '%%'
AND borough #borcond
AND admin_ref #stacond
AND id_ref #Numcond
AND category #cat
AND created_date #startDate
AND created_date #endDate
AND address LIKE #Addresscond
ORDER BY id_todays_date DESC
My C# code is as follows:
public void SQLQueryv2(
string AddressSel,
string startDateSel,
string endDateSel,
string incidentSel,
string borsel,
string stasel,
string numsel)
{
//this is filled in really
SqlConnection Connection = new SqlConnection(
"Data Source=;Initial Catalog=;User=;Password=;");
string sqlquery = <<as above>>
try
{
SqlCommand Command = new SqlCommand(sqlquery, Connection);
Connection.Open();
if (borsel == "Select Borough")
{
Command.Parameters.AddWithValue("#borcond", " = IS NOT NULL ");
}
else
{
Command.Parameters.AddWithValue("#borcond","= " + "'" + borsel + "'");
}
if (stasel == "Select Town")
{
Command.Parameters.AddWithValue("#stacond", " = IS NOT NULL ");
}
else
{
Command.Parameters.AddWithValue("#borcond","= "+ "'" + borsel + "'");
}
if (startDateSel == "")
{
Command.Parameters.AddWithValue("#startDate", " = IS NOT NULL");
}
else
{
Command.Parameters.AddWithValue(
"#startDate",
">= CONVERT(datetime," + "'" + startDateSel + "'" + ",103)");
}
if (endDateSel == "")
{
Command.Parameters.AddWithValue("#endDate", " = IS NOT NULL");
}
else
{
Command.Parameters.AddWithValue(
"#endDate",
">= CONVERT(datetime," + "'" + endDateSel + "'" + ",103)");
}
if (incidentSel == "Select Category")
{
Command.Parameters.AddWithValue(
"#cat",
" in ('cat a','cat b','cat c')");
}
else
{
Command.Parameters.AddWithValue(
"#cat",
" AND category =" + "'" + incidentSel + "'");
}
if (AddressSel == "")
{
Command.Parameters.AddWithValue("#Addresscond", "%%");
}
else
{
Command.Parameters.AddWithValue("#Addresscond","%" + AddressSel + "%");
}
if (numsel == "")
{
Command.Parameters.AddWithValue("#Numcond", " = IS NOT NULL ");
}
else
{
Command.Parameters.AddWithValue("#Numcond", "= " + "'" + numsel + "'");
}
//use adapter to populate dataset...
SqlDataAdapter DataAdapter = new SqlDataAdapter(sqlquery, Connection);
DataTable DataTable = new DataTable();
DataAdapter.SelectCommand = Command;
DataAdapter.Fill(DataTable);
//then bind dataset to the gridview
GridView1.AutoGenerateColumns = true;
GridView1.DataSource = DataTable;
GridView1.DataBind();
lblResults.Visible = true;
lblResults.ForeColor = System.Drawing.Color.Green;
lblResults.Text = "Your search has returned "
+ Dataset.Tables[0].Select(
"'Incident Number' IS NOT NULL").Length.ToString()
+ " records.";
}
catch (Exception err)
{
lblResults.Visible = true;
lblResults.ForeColor = System.Drawing.Color.Red;
lblResults.Text =
"An error has occurred loading data into the table view. ";
lblResults.Text += err.Message;
}
}
When run, the Gridview doesn't populate and the query (when investigated) it still has the variables and not the 'is nulls' or user inputs.
I think its something to so with the IF statements but i'm entirely sure. I think i just need another pair of eyes on this, any help would be appreciated.
Bit more info:
If i take out the sqlCommand bits it works perfectly with the IF statements, i'm trying to stop people from using malicious SQL queries.

This really isn't the correct way to use parameters. You should only assign values to them, not add comparison operators. Here's an example of how to "fix" your query for the #borcond parameter
...
AND ((#borcond = 'Select Borough' AND borough IS NOT NULL)
OR borough = #borcond)
...
Note: you don't need the equal sign with IS NOT NULL
And replace the if-else with
Command.Parameters.AddWithValue("#borcond", borsel);
You'll need to do similar changes for all of your parameters. The trick here is to basically move your if-else logic from the code into the sql query.
Additionally I don't think you need the location_address LIKE '%%' in your query as that just matches everything.

What juhar said. You've got the wrong idea about parameters. They're parameters and not text substitution. Here's an example of a valid query:
Select firstname, lastname from contacts
where ssn = #ssn
And in your code you'd say
Command.parameters.AddWithValue("#ssn","123-45-6789")

Related

C# Exception thrown: 'System.Data.SqlClient.SqlException' in System.Data.dll

Apologies in advance if I missed an answer to this somewhere but I wasn't quite finding it anywhere. So I'm building an application that scans PDF's of service orders our company gets, parses it, and inserts it into a SQL DB. The problem is at the end of this code. It successfully :
saves the original pdf in the proper folder
scans the pdf and parses it
inserts the correct data into the service order table
grabs PK of service order just created as we need that for the next batch of inserts
Here is where it gets hung up with a Exception thrown: 'System.Data.SqlClient.SqlException' in System.Data.dll
I foreach through all the instruments as there are multiples per Service Order, but it is erroring on this somewhere. to be clear I put a break point on the insert statement and all of the data is good and in the proper format ("string" int)
I feel like its in my connection maybe?
Anyways, thanks in advance for the help.
string filename = Path.GetFileName(FileUpload1.FileName);
FileUpload1.SaveAs(Server.MapPath("~/PDF/") + filename);
// Now we parse the PDF by creating a new ServiceOrder object and parsing from it.
ServiceOrder so = new ServiceOrder();
// Make sure we load the PDF from the correct path on the server
so.LoadPDF(Server.MapPath("~/PDF/") + filename);
String strConnString = "Data Source=127.0.0.0;Initial Catalog=SOMECATALOG;User ID=SOMEUSER;Password=SOMEPASSWORD";
// Insert Into Service Orders Table
string defaultdate = DateTime.Now.ToString("yyyy-MM-dd");
String strQuery = "insert into TServiceOrders (strServiceOrderNo, intStatusCodeID, strCustomerName, strCustomerNo, strCustomerAddress1, strCustomerAddress2, strCustomerAddress3, intRepID, strServiceDescription, strServiceRequestDate, strServiceOrderDate, strNotes) values ('"
+ so.ServiceOrderNumber.ToString() + "', 2, '"
+ so.CustomerContactName.ToString() + "', '"
+ so.CustomerNumber.ToString() + "', '"
+ so.CustomerContactAddress1.ToString() + "', '"
+ so.CustomerContactAddress2.ToString() + "', '"
+ so.CustomerContactAddress3.ToString() + "', 1, '', '"
+ defaultdate + "', '" + defaultdate + "', '')";
SqlConnection conn = new SqlConnection(strConnString);
SqlCommand cmd = new SqlCommand(strQuery, conn);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
// Grabbing latest primary key od service order just added for next instrument inserts
int lastid = 999999;
String strPKquery = "select top 1 intServiceOrderID from TServiceOrders order by intServiceOrderID desc";
SqlDataReader rdr = null;
SqlConnection conn2 = new SqlConnection(strConnString);
SqlCommand cmd2 = new SqlCommand(strPKquery, conn2);
try
{
conn2.Open();
rdr = cmd2.ExecuteReader();
while (rdr.Read())
{
lastid = (int)rdr["intServiceOrderID"];
}
}
finally
{
if (rdr != null)
{
rdr.Close();
}
if (conn2 != null)
{
conn2.Close();
}
}
// Insert Into Service Instruments Tables
SqlConnection conn3 = new SqlConnection(strConnString);
conn3.Open();
foreach (ServiceInstrument sin in so.ServiceInstruments)
{
string sim = "";
sim = sin.ServiceInstrumentModel;
if (String.IsNullOrEmpty(sim))
{
sim = "";
}
else
{
sim = sin.ServiceInstrumentModel.ToString();
}
string sid = "";
sid = sin.ServiceInstrumentDescription;
if (String.IsNullOrEmpty(sid))
{
sid = "";
}
else
{
sid = sin.ServiceInstrumentDescription.ToString();
}
string sis = "";
sis = sin.ServiceInstrumentSerial;
if (String.IsNullOrEmpty(sis))
{
sis = "";
}
else
{
sis = sin.ServiceInstrumentSerial.ToString();
}
string sih = "";
sih = sin.ServiceInstrumentHandle;
if (String.IsNullOrEmpty(sih))
{
sih = "";
}
else
{
sih = sin.ServiceInstrumentHandle.ToString();
}
string sip = "";
sip = sin.ServiceInstrumentParentAsset;
if (String.IsNullOrEmpty(sip))
{
sip = "";
}
else
{
sip = sin.ServiceInstrumentParentAsset.ToString();
}
String strQuery3 = "insert into TServiceInstruments values ('" + sim.ToString() + "', '" + sid.ToString() + "', '" + sis.ToString() + "', '" + sih.ToString() + "', " + sip.ToString() + ", " + lastid + ")";
SqlCommand cmd3 = new SqlCommand(strQuery3, conn3);
cmd3.ExecuteNonQuery();
}
conn3.Close();
When writing insert statements you should always specify the column names. This will protect the code from changes in the order of the columns in the table schema.
You are not using parameters in your sql statements, this leaves your code vulnerable to Sql Injection.
You should use using statements around your SqlConnection instances to ensure they are closed even when an Exception occurs.
Your logic is very difficult to follow, split your code until methods with meaningful names instead of having 1 "God" method that does everything.
If you follow those guidelines the problem will most likely solve itself in your refactoring.
Update Code Fragment
Note that you should always specify the correct types for your columns and the length if applicable. Also pass the actual value and never the string value.
const String strQuery3 = "INSERT INTO TServiceInstruments (sim, sid, sis, sih, sip, lid) VALUES (#sim, #sid, #sis, #sih, #sip, #lid)";
using(var conection = new SqlConnection(strConnString))
using(SqlCommand command = new SqlCommand(strQuery3, connection))
{
command.Parameters.Add(new SqlParameter("#sim", SqlDbType.VarChar, 200){Value = sim});
command.Parameters.Add(new SqlParameter("#sid", SqlDbType.VarChar, 200){Value = sid});
command.Parameters.Add(new SqlParameter("#sis", SqlDbType.VarChar, 200){Value = sis});
command.Parameters.Add(new SqlParameter("#sih", SqlDbType.VarChar, 200){Value = sih});
command.Parameters.Add(new SqlParameter("#sip", SqlDbType.Int){Value = sip});
command.Parameters.Add(new SqlParameter("#lid", SqlDbType.Int){Value = lid});
connection.Open();
command.ExecuteNonQuery();
}
Final note: You really need to learn how to read Exceptions and this includes the Stack Trace which points directly to the line in the call stack where the Exception originated. If you can understand this then debugging becomes much easier.
Maybe this doesn't deserve to be an answer, but I'm trying to build some reputation, so here goes :).
I suspect that your error lies in the "insert into TServiceInstruments ..." statement. Namely, you are giving the table more (or less) columns. As a good practice, always specify the columns, like this:
insert into TServiceInstruments (column1, column2, column3)
values (1, 2, 3)

How to search SQL database and display in C# listview

I need to filter an SQL database using C# to display it in a windowsFormsHost.
For that, I created a text box in which you input the required string. Using this input, the code uses the text to search through the database and display on clicking a refresh button.
The refresh button works and is done, I just need to create the list with the selected rows according to my filter.
Here is the code, which states that no value is returned:
private string GetPassengerList(string sPasssenger)
{
string sPasssengerL = textBoxPassengerName.Text;
if (sPasssenger.Trim().Length > 0)
{
string sToTime = dtpToDate.Value.Year.ToString("D4") + #"/" + dtpToDate.Value.Month.ToString("D2") + #"/" + dtpToDate.Value.Day.ToString("D2");
sToTime += #" " + dtpToTime.Value.Hour.ToString("D2") + #":" + dtpToTime.Value.Minute.ToString("D2") + #":" + dtpToTime.Value.Second.ToString("D2");
string sFromTime = dtpFromDate.Value.Year.ToString("D4") + #"/" + dtpFromDate.Value.Month.ToString("D2") + #"/" + dtpFromDate.Value.Day.ToString("D2");
sFromTime += #" " + dtpFromTime.Value.Hour.ToString("D2") + #":" + dtpFromTime.Value.Minute.ToString("D2") + #":" + dtpFromTime.Value.Second.ToString("D2");
string sSqlSelect = #"SELECT Passenger FROM ";
string sSqlWhere = #" WHERE (Created BETWEEN '" + sFromTime + #"' AND '" + sToTime + #"')";// and (IATA='" + sIata + #"')";
string sSqlLike = #" LIKE '%" + sPasssengerL + "'%";
SqlDataReader sqlReader = null;
try {
SqlCommand sqlCommand = new SqlCommand(sSqlSelect + #"dbo.BagData" + sSqlWhere + sSqlLike, this.dbConnection);
sqlReader = sqlCommand.ExecuteReader();
if(!sqlReader.Read()) {
sqlReader.Close();
sqlCommand.CommandText = sSqlSelect + #"dbo.BagDataHistory" + sSqlWhere + sSqlLike;
sqlReader = sqlCommand.ExecuteReader();
if(!sqlReader.Read()) {
sqlReader.Close();
sqlCommand.CommandText = sSqlSelect + #"dbo.BagDataArchive" + sSqlWhere + sSqlLike;
sqlReader = sqlCommand.ExecuteReader();
if(!sqlReader.Read()) {
sqlReader.Close();
}
}
}
if(!sqlReader.IsClosed) {
sPasssengerL = this.GetSqlDataString(#"Passenger", sqlReader);
sqlReader.Close();
}
}
catch(SqlException x) {
MessageBox.Show(#"GetPassengerName(): SQL Exception: " + x.Message, this.GetHashString("Error"), MessageBoxButton.OK, MessageBoxImage.Error);
}
catch(Exception ex) {
MessageBox.Show(#"GetPassengerName(): General Exception: " + ex.Message, this.GetHashString("Error"), MessageBoxButton.OK, MessageBoxImage.Error);
}
finally {
if(sqlReader != null) {
if(!sqlReader.IsClosed) {
sqlReader.Close();
}
}
}
return sPasssengerL;
}
}
You have a few errors in the code you posted.
Using concatenated strings instead of parameters in your sql query.
Re-declaring a variable with the same name as the functions parameter. You are declaring another passenger variable sPasssengerL needlessly in the function now.
Not returning a string value from the function. Your edited code shows the function returning the seemingly unneeded extra passenger variable sPasssengerL now.
Your LIKE statement did not include which column it is checking
against.
I cleaned up the code a little, leaving the sSqlWhere in case that was oddly delcared outside your example. This also shows how to add the first column of data to a listview as you've requested.
EDIT: Per your comment on the original question I've updated the code
to show your sSqlWhere variable.
private void GetPassengerList()
{
string sPassenger = textBoxPassengerName.Text;
if (sPassenger.Trim().Length > 0)
{
string sToTime = dtpToDate.Value.Year.ToString("D4") + #"/" + dtpToDate.Value.Month.ToString("D2") + #"/" + dtpToDate.Value.Day.ToString("D2");
sToTime += #" " + dtpToTime.Value.Hour.ToString("D2") + #":" + dtpToTime.Value.Minute.ToString("D2") + #":" + dtpToTime.Value.Second.ToString("D2");
string sFromTime = dtpFromDate.Value.Year.ToString("D4") + #"/" + dtpFromDate.Value.Month.ToString("D2") + #"/" + dtpFromDate.Value.Day.ToString("D2");
sFromTime += #" " + dtpFromTime.Value.Hour.ToString("D2") + #":" + dtpFromTime.Value.Minute.ToString("D2") + #":" + dtpFromTime.Value.Second.ToString("D2");
string sSqlSelect = #"SELECT Passenger FROM ";
string sSqlWhere = #" WHERE (Created BETWEEN #startDate AND #endDate)";
// I assume this is looking for passenger. Change appropriately.
string sSqlLike = #"AND Passenger LIKE #name";
string searchTerm = "%" + sPassenger + "%";
SqlDataReader sqlReader = null;
try
{
SqlCommand sqlCommand = new SqlCommand(sSqlSelect + #"dbo.BagData" + sSqlWhere, parentWindow.dbConnection);
sqlReader = sqlCommand.ExecuteReader();
if (!sqlReader.Read())
{
sqlReader.Close();
sqlCommand.CommandText = sSqlSelect + #"dbo.BagDataHistory" + sSqlWhere + sSqlLike;
sqlCommand.Parameters.Add(new SqlParameter("#name", searchTerm));
sqlCommand.Parameters.Add(new SqlParameter("#startDate", sToTime));
sqlCommand.Parameters.Add(new SqlParameter("#endDate", sFromTime));
sqlReader = sqlCommand.ExecuteReader();
if (!sqlReader.Read())
{
sqlReader.Close();
sqlCommand.CommandText = sSqlSelect + #"dbo.BagDataArchive" + sSqlWhere + sSqlLike;
sqlReader = sqlCommand.ExecuteReader();
// This will loop through your returned data and add
// an item to a list view (listView1) for each row.
while (sqlReader.Read())
{
ListViewItem lvItem = new ListViewItem();
lvItem.SubItems[0].Text = sqlReader[0].ToString();
lvItem.SubItems.Add(sqlReader[0].ToString());
listView1.Items.Add(lvItem);
}
sqlReader.Close();
}
}
if (!sqlReader.IsClosed)
{
sPassenger = parentWindow.GetSqlDataString(#"Passenger", sqlReader);
sqlReader.Close();
}
}
catch (SqlException x)
{
MessageBox.Show(#"GetPassengerName(): SQL Exception: " + x.Message, parentWindow.GetHashString("Error"), MessageBoxButton.OK, MessageBoxImage.Error);
}
catch (Exception ex)
{
MessageBox.Show(#"GetPassengerName(): General Exception: " + ex.Message, parentWindow.GetHashString("Error"), MessageBoxButton.OK, MessageBoxImage.Error);
}
finally
{
if (sqlReader != null)
{
if (!sqlReader.IsClosed)
{
sqlReader.Close();
}
}
}
}
}
NOTE: There are other places this code can be cleaned up and simplified but that is beyond the scope of this question.
Check your variables, you've declared sSqlSelect and sSqlLike but not sSqlWhere which you are using in your queries.
a) your function will not compile:
- Missing ";" in several lines,
- local variable declaration "sPessanger" in line 2 conflicts with parameter name ...
b) you never return a value. At least you need a single "return sPassenger;" somewhere in the code to return the selected value.
c) bad style using sql injection. As already stated in the comments, use parameters in your SQL.
d) as far as i can see, you are selecting only a single value from your resultset, or is the GetSqlDataString function supposed to do the job?

MySql command to update info in C#

I'm working on a personal project where i want to get information of a customer from my database. However, i keep failing. The sql command i have:
"SELECT * FROM `customer` WHERE `ID` =#_ID AND `Naam` LIKE '" + tbKlantZoeken.Text + "'AND `E-mail` =#_EMAIL AND `Telefoon` =#_TEL"
The database connection is working, and another code related to the database is working aswell. So i guess it is my sql code? If not, Here's my code where i use it:
//Get info
db_connection();
MySqlCommand cmdZoeken = new MySqlCommand();
cmdZoeken.CommandText = "SELECT * FROM `customer` WHERE `ID` =#_ID AND `Naam` LIKE '" + tbKlantZoeken.Text + "'AND `E-mail` =#_EMAIL AND `Telefoon` =#_TEL";
cmdZoeken.Parameters.AddWithValue("#_ID", _ID);
cmdZoeken.Parameters.AddWithValue("#_EMAIL", _EMAIL);
cmdZoeken.Parameters.AddWithValue("#TEL", _TEL);
cmdZoeken.Connection = connect;
MySqlDataReader tbZoeken = cmdZoeken.ExecuteReader();
if (tbZoeken.Read())
{
connect.Close();
return true;
}
else
{
return false;
}
}
Other part:
//use code
db_connection();
string _ID = "ID";
string _EMAIL = "EMAIL";
string _TEL = "TEL";
try
{
bool Z = Klant_zoeken(_ID, _EMAIL, _TEL);
if (Z)
{
tbKResultaat.Text = _ID + " " + " " + _EMAIL + " " + _TEL;
}
}
catch
{
throw;
}
At this part, when it fails, the "throw" doesn't work aswell. It just crashes, but i think that is a question for another time...
Thanks in advance!
Check with this:- You have missing space between some words. Also add % mark for like according to your requirement. Unless use as Naam` = tbKlantZoeken.Text without like
"SELECT * FROM `customer` WHERE `ID` =#_ID AND `Naam` LIKE '" +
tbKlantZoeken.Text + "' AND `E-mail` =#_EMAIL AND `Telefoon` =#_TEL";
Try this
/Get info
db_connection();
MySqlCommand cmdZoeken = new MySqlCommand();
cmdZoeken.CommandText = "SELECT * FROM customer WHERE ID =#_ID AND Naam LIKE '" + tbKlantZoeken.Text + "%'AND E-mail =#_EMAIL AND Telefoon =#_TEL";
cmdZoeken.Parameters.AddWithValue("#_ID", _ID);
cmdZoeken.Parameters.AddWithValue("#_EMAIL", _EMAIL);
cmdZoeken.Parameters.AddWithValue("#TEL", _TEL);
cmdZoeken.Connection = connect;
MySqlDataReader tbZoeken = cmdZoeken.ExecuteReader();
if (tbZoeken.Read())
{
connect.Close();
return true;
}
else
{
return false;
}
}
You should remove single quates from Table_name and Column_name-
try select statement like this-
cmdZoeken.CommandText = "SELECT * FROM customer WHERE ID =#_ID AND Naam LIKE '%" + tbKlantZoeken.Text + "%'AND E-mail =#_EMAIL AND Telefoon =#_TEL";

SQL DateDiff inconsistency

When I run the following script on my SQL database (from the management studio) I get the results I expect -
SELECT *
FROM [Case]
WHERE ABS((DATEDIFF(DAY, [DateAccident], '2013-01-01'))) < 100;
When I increase / decrease the value 100, I get more / less matches exactly as expected.
However, when I attempt to produce the same result from my WinForms app (in C#) I get far more results than I should -
public static DataTable DOACases(DateTime doa, int days)
{
try
{
DataTable table = new DataTable();
string sqlText = "SELECT * " +
"FROM [Case] " +
"WHERE ABS((DATEDIFF(DAY, [DateAccident], " + doa.ToString().Substring(0,10) + "))) < " + days.ToString() + ";";
SqlCommand sqlCom = new SqlCommand(sqlText);
table = Express.GetTable(sqlCom);
return table;
}
catch (Exception eX)
{
throw new Exception("Case: DOACases(Date)" + Environment.NewLine + eX.Message);
}
}
I do not know why
PS. Express.GetTable(sqlCom) simply creates a connection on the database and the necessary code to fill a DataTable using a DataReader and has worked hundreds of times, so I doubt the issue is there.
Thanks to allo-man, using parameters worked.
The final code looked as follows -
public static DataTable DOACases(DateTime doa, int days)
{
try
{
DataTable table = new DataTable();
string sqlText = "SELECT * " +
"FROM [Case] " +
"WHERE ABS((DATEDIFF(DAY, [DateAccident], #Date))) < #Days;";
SqlCommand sqlCom = new SqlCommand(sqlText);
sqlCom.Parameters.Add("#Date", SqlDbType.Date).Value = doa;
sqlCom.Parameters.Add("#Days", SqlDbType.Int).Value = days;
table = Express.GetTable(sqlCom);
return table;
}
catch (Exception eX)
{
throw new Exception("Case: DOACases(Date)" + Environment.NewLine + eX.Message);
}
}
You better use parameters but here the problem is
'" + doa.ToString("yyyy-MM-dd" , CultureInfo.InvariantCulture) + "'
you need single quotes

Code repeating itself causing duplicate records in database

this problem is a bit of a difficult one to explain but here it goes. I have a function which adds a record to a MySQL Database online from a local SQLiteDatabase. A function is first called to retrieve the local data and each line is sent to the upload function which adds the record to the online MySQL Database. When these functions are called from a another function A it works fine but when called from a different function. Function B duplicate records are entered into the database.
During debugging to try and resolve the problem I find that when it is duplicating records it is going to cmd.executeNonQuery() then going to the next couple of line but then for no reason will go back up to cmd.executeNonQuery() therefore duplicating the record. The code is below
private void uploadDatabase(string company, string oldCompany, string companyURL, string loginUsername, string oldUsername, string password, string type, string perform, string direction)
{
Boolean recordFound = false;
recordFound = checkRecordNotExist(company, loginUsername);
MySQLDBWork dbase = new MySQLDBWork();
try
{
dbase.openConnection();
if (perform == "insert" && !recordFound)
{
string query = "INSERT INTO `" + username + "` (pas_company, pas_companyURL, pas_username, pas_password, pas_type) "
+ "VALUES ('" + company + "', '" + companyURL + "', '" + loginUsername + "', '" + password + "', '" + type + "')";
Console.WriteLine("Query: " + query);
MySqlCommand cmd = new MySqlCommand(query, dbase.conn);
cmd.ExecuteNonQuery();
recordFound = true;
query = "";
company = "";
loginUsername = "";
cmd.Dispose();
}
if (perform == "delete")
{
string query = "DELETE FROM `" + username + "` WHERE pas_company='" + company + "' AND pas_username='" + loginUsername + "'";
dbase.performQuery(query);
}
}
catch (MySqlException ex)
{
Console.WriteLine("Adding Online Error: " + ex.Message);
}
catch (Exception ex)
{
Console.WriteLine("General Exception: " + ex.Message);
}
finally
{
dbase.closeConnection();
//dbase.conn.Dispose();
company = null;
loginUsername = null;
}
}
The problem is within the if statement perform == "insert" && !recordFound.
I'm not sure if the code above will help to solve the problem but this is the function that is going wrong when called from function b but works fine from function A. Thanks for any help and suggestions you can offer.
then going to the next couple of line
but then for no reason will go back up
to cmd.executeNonQuery()
That sounds like a simple multithreading problem. The function is accessed again from a different thread. So what's happening is that it goes through your check exists in both threads before it is inserted in either, and then it is inserted in both.
So, create a lock, and lock the code... something like this:
private System.Object uploadLock = new System.Object();
private void uploadDatabase(string company, string oldCompany, string companyURL, string loginUsername, string oldUsername, string password, string type, string perform, string direction)
{
lock(uploadLock ) {
Boolean recordFound = false;
recordFound = checkRecordNotExist(company, loginUsername);
MySQLDBWork dbase = new MySQLDBWork();
try
{
dbase.openConnection();
if (perform == "insert" && !recordFound)
{
string query = "INSERT INTO `" + username + "` (pas_company, pas_companyURL, pas_username, pas_password, pas_type) "
+ "VALUES ('" + company + "', '" + companyURL + "', '" + loginUsername + "', '" + password + "', '" + type + "')";
Console.WriteLine("Query: " + query);
MySqlCommand cmd = new MySqlCommand(query, dbase.conn);
cmd.ExecuteNonQuery();
recordFound = true;
query = "";
company = "";
loginUsername = "";
cmd.Dispose();
}
if (perform == "delete")
{
string query = "DELETE FROM `" + username + "` WHERE pas_company='" + company + "' AND pas_username='" + loginUsername + "'";
dbase.performQuery(query);
}
}
catch (MySqlException ex)
{
Console.WriteLine("Adding Online Error: " + ex.Message);
}
catch (Exception ex)
{
Console.WriteLine("General Exception: " + ex.Message);
}
finally
{
dbase.closeConnection();
//dbase.conn.Dispose();
company = null;
loginUsername = null;
}
}
}
The lock will allow access to the code to only on thread at a time. So no more duplications.
My advice to you:
Always use transactions and you won't be able make duplications. You also may make LoginName column unique and properly handle db error.
DO NOT concatenate string to build query, please. Use command parameters - simplest way escape SQL injection. Currently you have at least 4 vulnerable parameter. Awesome ;)
I would suggest putting a breakpoint on cmd.ExecuteNonQuery(); and inspecting the call stack each time it is hit, paying special attention to the second/duplicate hit. Also pay attention to which thread the breakpoint is being hit on. Doing these things should point you to the problem.

Categories

Resources