checking if record in database in mysql using c# - c#

Newbie here, I am currently creating a tool that will parse a text file "namelist.txt" contains names. my tool will check if each name are already in my database. if not exist it will write to another file "new_name.log".
my code is something like this.
in my query command I used count(*) to return the count
string DBNAME= "SELECT count(*) FROM tbl_namelist WHERE name = '" + name + "'";
conn.Open();
MySqlCommand DBCmd = new MySqlCommand(DBNAME, conn);
MySqlDataReader reader = DBCmd.ExecuteReader();
while (reader.Read())
{
if (reader == 0)
try
{
//label2.Text = reader.GetString(0);
sds.WriteLine("New Name: " + name+ " " + reader.GetString(0));
}
catch (Exception dd)
{
sds.WriteLine("duplicate Name: " + name+ " " + reader.GetString(0));
}
I dont know if i read the correct info "reader.read" to give me an integer output "count".
please assist me thanks.

don't use MySQLDataReader but instead use command's ExecuteNonScalar to fetch single value.
string DBName = "SELECT count(*) FROM tbl_namelist WHERE name = #name";
using (MySqlConnection conn = new MySqlConnection("connectionString Here"))
{
using (MySqlCommand comm = new MySqlCommand())
{
comm.Connection = conn;
comm.CommandText = DBName;
comm.CommandType = CommandType.Text;
comm.Parameters.AddWithValue("#name", name);
try
{
conn.Open();
int totalCount = Convert.ToInt32(comm.ExecuteScalar());
if (totalCount == 0)
{
sds.WriteLine("New Name: " + name + " " + totalCount);
}
else
{
// when not zero
}
}
catch( MySqlException ex)
{
// error here
}
}
}
use USING-statement and parameterized your query.

count(*) return int and you should change reader.GetString(0) to reader.GetInt32(0) and in
if(reader==0) to if (reader.GetInt32(0)==0) and it will work

Related

Issue with Open DataReader which must be closed first

I am getting the following error in my code:
"There is already an open DataReader associated with this Command
which must be closed first."
I have two SqlDataReaders and I made sure that I closed the first one after loading the DataViewGrid.
Below is the function that is giving me the issue. I marked the line that is throwing the error. I've tried variations with 'try' and 'using', I've tried to rename diff SqlConnections, SqlDataReaders and SqlCommands. I am at a loss here.
Can I not have an open SqlDataReader and SqlCommand open at the same time on one connection?
private void ApprovedTransferAction(int rowNum) {
bool foundFlag = false;
//int XferQty = (int)gridData.Rows[rowNum].Cells["FinalQty"].Value;
string PorgID = "";
using (SqlConnection conn = new SqlConnection(Global.connString)) {
conn.Open();
// Locate id in PorgReqs
string sqlSelectQuery = "SELECT id FROM PorgReqs WHERE location_id = #NewLocationID AND vendor_id = #VendorID AND item_id = #Item";
using (SqlCommand sqlSelect = new SqlCommand(sqlSelectQuery, conn)) {
sqlSelect.Parameters.Add("#NewLocationID", SqlDbType.VarChar, 60).Value = gridData.Rows[rowNum].Cells["NewLocation"].Value;
sqlSelect.Parameters.Add("#VendorID", SqlDbType.VarChar, 60).Value = gridData.Rows[rowNum].Cells["Vendor"].Value;
sqlSelect.Parameters.Add("#Item", SqlDbType.VarChar, 60).Value = gridData.Rows[rowNum].Cells["Item"].Value;
using (SqlDataReader sqlDataReader2 = sqlSelect.ExecuteReader()) {
// If Item is found at Target Location; FinalQty of Source Added to AddlQty of Target
if (sqlDataReader2.HasRows) {
sqlDataReader2.Read();
PorgID = Convert.ToString(sqlDataReader2["id"]);
MessageBox.Show("Found ID: " + PorgID);
string sqlUpdateQuery = "UPDATE PorgReqs SET AddlQty += #XferQty WHERE id = #ID";
using (SqlCommand sqlUpdate = new SqlCommand(sqlUpdateQuery, conn)) {
sqlUpdate.Parameters.Add("#XferQty", SqlDbType.Int).Value = (int)gridData.Rows[rowNum].Cells["FinalQty"].Value;
sqlUpdate.Parameters.Add("#ID", SqlDbType.Int).Value = sqlDataReader2["id"];
sqlUpdate.CommandType = CommandType.Text;
sqlUpdate.ExecuteNonQuery();
} // End sqlUpdate Command
} else { // Item was not found at Target location
string sqlUpdateQuery = "UPDATE PorgReqs SET " +
" location_id = #TargetLoc, " +
" requirement_location_id = #TargetLoc, " +
" ship_to_location_id = #TargetLoc " +
" WHERE " +
" location_id = #SourceLoc AND " +
" vendor_id = #VendorID AND " +
" item_id = #Item";
using (SqlCommand sqlUpdate = new SqlCommand(sqlUpdateQuery, conn)) {
sqlUpdate.Parameters.Add("#TargetLoc", SqlDbType.Int).Value = gridData.Rows[rowNum].Cells["NewLocation"].Value;
sqlUpdate.Parameters.Add("#SourceLoc", SqlDbType.Int).Value = gridData.Rows[rowNum].Cells["Location"].Value;
sqlUpdate.Parameters.Add("#VendorID", SqlDbType.Int).Value = gridData.Rows[rowNum].Cells["Vendor"].Value;
sqlUpdate.Parameters.Add("#Item", SqlDbType.VarChar, 60).Value = gridData.Rows[rowNum].Cells["Item"].Value;
sqlUpdate.CommandType = CommandType.Text;
sqlUpdate.ExecuteNonQuery(); // ERROR HERE
} // End sqlUpdate Command
} // End Else
sqlDataReader2.Close();
}
/*} catch (Exception ex) {
Console.WriteLine(ex.Message);
MessageBox.Show("Try SQLReader: " + ex.Message);
} */
} // End sqlSelect Command
} // End SQL Connection
// See if id exists in grid
MessageBox.Show("Checking Grid");
foreach (DataGridViewRow row in gridData.Rows) {
if (foundFlag == true)
break;
else if (row.Cells["id"].Value.ToString() == PorgID) {
// Update grid
row.Cells["AddlQty"].Value = Convert.ToInt32(gridData.Rows[rowNum].Cells["FinalQty"].Value) + Convert.ToInt32(row.Cells["AddlQty"].Value);
row.Cells["FinalQty"].Value = Convert.ToInt32(row.Cells["RecQty"].Value) + Convert.ToInt32(row.Cells["AddlQty"].Value);
foundFlag = true;
MessageBox.Show("Found: " + foundFlag);
} // End If
} // End ForEach
// Remove the Row from the Grid
gridData.Rows.RemoveAt(rowNum);
}
Just add MultipleActiveResultSets=true to your connection string.

Invalid attempt to call read when reader is closed when inserting data

i have a button that when clicked inserts data from textbox and combobox fields into database tables, but every time i insert it gives me "Invalid attempt to call read when reader is closed". How can i get rid of this error. And tips on optimising the code are welcome, because i know im a total noob. thanks
private void btnSave_Click(object sender, RoutedEventArgs e)
{
try
{
SqlConnection sqlCon = new SqlConnection(#"Data Source=(localdb)\mssqllocaldb; Initial Catalog=Storagedb;");
sqlCon.Open();
string Query1 = "insert into location(Storage, Shelf, columns, rows) values(" + txtWarehouse.Text + ", " + txtShelf.Text + ", " + txtColumn.Text + ", " + txtRow.Text + ")";
SqlCommand sqlCmd = new SqlCommand(Query1, sqlCon);
SqlDataAdapter dataAdp = new SqlDataAdapter(sqlCmd);
dataAdp.SelectCommand.ExecuteNonQuery();
sqlCon.Close();
}
catch (Exception er)
{
MessageBox.Show(er.Message);
}
try
{
SqlConnection sqlCon = new SqlConnection(#"Data Source=(localdb)\mssqllocaldb; Initial Catalog=Storagedb;");
sqlCon.Open();
string Query3 = "SELECT LOCATION_ID FROM LOCATION WHERE storage='" + txtWarehouse.Text + "' AND shelf='" + txtShelf.Text + "' AND columns='"
+ txtColumn.Text + "' AND rows='" + txtRow.Text + "'";
SqlCommand sqlCmd1 = new SqlCommand(Query3, sqlCon);
SqlDataReader dr = sqlCmd1.ExecuteReader(); ;
while (dr.Read())
{
string LocationId = dr[0].ToString();
dr.Close();
string Query2 = "insert into product(SKU, nimetus, minimum, maximum, quantity,location_ID,category_ID,OrderMail_ID) values ('" + txtSku.Text + "','" + txtNimetus.Text + "', '"
+ txtMin.Text + "', '" + txtMax.Text + "', '" + txtQuan.Text + "', '" + LocationId + "', '" + (cbCat.SelectedIndex+1) + "', '" + (cbMail.SelectedIndex+1) + "')";
SqlCommand sqlCmd = new SqlCommand(Query2, sqlCon);
SqlDataAdapter dataAdp = new SqlDataAdapter(sqlCmd);
dataAdp.SelectCommand.ExecuteNonQuery();
}
sqlCon.Close();
}
catch (Exception ed)
{
MessageBox.Show(ed.Message);
}
}
Let's try to make some adjustments to your code.
First thing to consider is to use a parameterized query and not a
string concatenation when you build an sql command. This is mandatory
to avoid parsing errors and Sql Injections
Second, you should encapsulate the disposable objects in a using statement
to be sure they receive the proper disposal when you have finished to
use them.
Third, you can get the LOCATION_ID from your table without running a
separate query simply adding SELECT SCOPE_IDENTITY() as second batch to your first command. (This works only if you have declared the LOCATION_ID field in the first table as an IDENTITY column)
Fourth, you put everything in a transaction to avoid problems in case
some of the code fails unexpectedly
So:
SqlTransaction tr = null;
try
{
string cmdText = #"insert into location(Storage, Shelf, columns, rows)
values(#storage,#shelf,#columns,#rows);
select scope_identity()";
using(SqlConnection sqlCon = new SqlConnection(.....))
using(SqlCommand cmd = new SqlCommand(cmdText, sqlCon))
{
sqlCon.Open();
using( tr = sqlCon.BeginTransaction())
{
// Prepare all the parameters required by the command
cmd.Parameters.Add("#storage", SqlDbType.Int).Value = Convert.ToInt32(txtWarehouse.Text);
cmd.Parameters.Add("#shelf", SqlDbType.Int).Value = Convert.ToInt32(txtShelf.Text);
cmd.Parameters.Add("#columns", SqlDbType.Int).Value = Convert.ToInt32(txtColumn.Text );
cmd.Parameters.Add("#rows", SqlDbType.Int).Value = Convert.ToInt32(txtRow.Text);
// Execute the command and get back the result of SCOPE_IDENTITY
int newLocation = Convert.ToInt32(cmd.ExecuteScalar());
// Set the second command text
cmdText = #"insert into product(SKU, nimetus, minimum, maximum, quantity,location_ID,category_ID,OrderMail_ID)
values (#sku, #nimetus,#min,#max,#qty,#locid,#catid,#ordid)";
// Build a new command with the second text
using(SqlCommand cmd1 = new SqlCommand(cmdText, sqlCon))
{
// Inform the new command we are inside a transaction
cmd1.Transaction = tr;
// Add all the required parameters for the second command
cmd1.Parameters.Add("#sku", SqlDbType.NVarChar).Value = txtSku.Text;
cmd1.Parameters.Add("#nimetus",SqlDbType.NVarChar).Value = txtNimetus.Text;
cmd1.Parameters.Add("#locid", SqlDbType.Int).Value = newLocation;
.... and so on for the other parameters required
cmd1.ExecuteNonQuery();
// If we reach this point the everything is allright and
// we can commit the two inserts together
tr.Commit();
}
}
}
}
catch (Exception er)
{
// In case of exceptions do not insert anything...
if(tr != null)
tr.Rollback();
MessageBox.Show(er.Message);
}
Notice that in the first command I use parameters of type SqlDbType.Int because you haven't used single quotes around your text. This should be verified against the real data type of your table columns and adjusted to match the type. This is true as well for the second command where you put everything as text albeit some of those fields seems to be integer (_location_id_ is probably an integer). Please verify against your table.

Insert list of rows

I'm trying to a simple insert list of rows from a DataGridView to a database.
I have made a checkedbox that upon checked, the item will be added to the DataGridView. Now i'm attempting to do the INSERT part. This what I have come up so far:
try
{
string strAppointment = "SELECT appointmentID FROM APPOINTMENT WHERE appointmentID=#searchappointmentID";
SqlCommand cmdAppointment = new SqlCommand(strAppointment, connection);
cmdAppointment.Parameters.AddWithValue("#searchappointmentID", txtAppointmentID.Text);
connection.Open();
for (int i = 0; i < dataPrescription.Rows.Count; i++)
{
string firstColumn = dataPrescription[0, dataPrescription.CurrentCell.RowIndex].Value.ToString();
string strMedications = "SELECT medicationID FROM MEDICATION WHERE medicationName= ('" + firstColumn + "')";
SqlCommand cmdMedications = new SqlCommand(strMedications, connection);
SqlDataReader readMedications = cmdMedications.ExecuteReader();
if (readMedications.Read())
{
string getDrugID = readMedications["medicationID"].ToString();
string strPrescriptions = "INSERT INTO PRESCRIPTION (appointmentID, medicationID, quantity) " +
"VALUES (#insertAppointment, "
+ getDrugID + ", "
+ dataPrescription.Rows[i].Cells["columnQuantity"].Value + ");";
SqlCommand cmdPrescriptions = new SqlCommand(strPrescriptions, connection);
cmdPrescriptions.Parameters.AddWithValue("#insertAppointment", txtAppointmentID.Text);
prescriptionsResult = cmdAppointment.ExecuteNonQuery();
}
readMedications.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error");
}
finally
{
connection.Close();
}
Right now it giving me this error: "There is already an open DataReader associated with the command which must be closed first". I don't know what I've done wrong
Try this: (initialize the datareader)
for (int i = 0; i < dataPrescription.Rows.Count; i++)
{
string firstColumn = dataPrescription[0, dataPrescription.CurrentCell.RowIndex].Value.ToString();
string strMedications = "SELECT medicationID FROM MEDICATION WHERE medicationName= ('" + firstColumn + "')";
SqlCommand cmdMedications = new SqlCommand(strMedications, connection);
SqlDataReader dr = new SqlDataReader(); //Insert this line in your code
SqlDataReader readMedications = cmdMedications.ExecuteReader();
It looks like you're trying to execute a command using a connection that's occupied with the reader, and I would look at that as being the problem. Instead of trying to execute the insert inside the reader, try reading the data to a collection and closing the reader, then iterating the connection to make you're updates.

How do I delete a row from a Microsoft Access table using c#

I've tried this code:
string sql = " DELETE FROM HotelCustomers WHERE [Room Number] =" + textBox1.Text;
OleDbConnection My_Connection = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source= c:\\Users\\Documents\\HotelCustomersOld.mdb");
My_Connection.Open();
OleDbCommand My_Command = new OleDbCommand(sql, My_Connection);
My_Command.ExecuteNonQuery();
Error: Data type mismatch in criteria expression, at the line:
My_Command.ExecuteNonQuery();
Use parametrized query to avoid all kind of errors
string sql = " DELETE FROM HotelCustomers WHERE [Room Number] =?";
using(OleDbConnection My_Connection = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source= c:\\Users\\Documents\\HotelCustomersOld.mdb"))
{
My_Connection.Open();
OleDbCommand My_Command = new OleDbCommand(sql, My_Connection);
My_Command.Parameters.Add("#p1", textBox1.Text);
My_Command.ExecuteNonQuery();
}
In your case the Room NUmber field is of Text type so, you need to enclose the value in single quotes, but this is really wrong. You expose your code to maliciuos text written by your user inside the text box. A very simple and funny example here
Which type is your [Room Number] column? If it is a string then you have to write the value with inverted comma or quotation mark (I'm not sure which of both is used in Access).
string sql = " DELETE FROM HotelCustomers WHERE [Room Number] = '" + textBox1.Text + "'";
To avoid SQL injektion you should use Parameters instead of the string operation.
public static void DeleteLine(string kv)
{
OleDbConnection myConnection = GetConnection();
string myQuery = "DELETE FROM Cloth WHERE [ClothName] = '" + kv + "'";
OleDbCommand myCommand = new OleDbCommand(myQuery, myConnection);
try
{
myConnection.Open();
myCommand.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine("Exception in DBHandler", ex);
}
finally
{
myConnection.Close();
}
}
try
{
OleDbConnection con = new OleDbConnection("provider = microsoft.ace.oledb.12.0;data source = E:\\Sohkidatabase\\Sohki.accdb");
con.Open();
str = "select * from compny_info where id=" + comboBox1.Text.Trim() + "";
com = new OleDbCommand(str, con);
OleDbDataReader reader = com.ExecuteReader();
if (reader.Read())
{
textBox1.Text = reader["regis_no"].ToString();
textBox2.Text = reader["comp_oner"].ToString();
textBox3.Text = reader["comp_name"].ToString();
textBox4.Text = reader["comp_add"].ToString();
textBox5.Text = reader["tin_no"].ToString();
textBox6.Text = reader["email"].ToString();
}
con.Close();
reader.Close();
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
public static void DeleteLine(string kv) {
OleDbConnection myConnection = GetConnection();
string myQuery = "DELETE FROM Cloth WHERE [ClothName] = '" + kv + "'" ;
}

Webservice+consumer c# error Server was unable to process request. ---> The connection is already open

i have a webservice and a comsumer, the webservice has its methode where it returns data from a mysql database.
in the comsumer i called
WebService.Service1 Service = new WebService.Service1();
in the beginning (not within a methode)
when the consumer starts asking for data it will be 20 requests within 10 minutes first 15-18 requests worked perfectly but the last few times it returns the error
Server was unable to process request. ---> The connection is already
open.
I hope i provided enough information like this, i rather not post the code.
This is the methode of the webservice:
public string GetAnswer(string Question, string Option1, string Option2, string Option3, string Option4)
{
string connstring = "Server=Server;Port=3306;Database=DB;UID=User;password=pw;";
MySqlConnection conn = new MySqlConnection(connstring);
MySqlCommand command = conn.CreateCommand();
command.CommandText = "SELECT * FROM `tbl` where `Question` = '" + Question + "' LIMIT 1";
conn.Open();
MySqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
string TheAnswer = "";
while (reader.Read())
{
string question = reader["Question"].ToString();
string answer = reader["Answer"].ToString();
if (Option1.Equals(answer))
TheAnswer = Option1;
if (Option2.Equals(answer))
TheAnswer = Option2;
if (Option3.Equals(answer))
TheAnswer = Option3;
if (Option4.Equals(answer))
TheAnswer = Option4;
}
conn.Close();
conn.Dispose();
return TheAnswer;
}
else
{
MySqlCommand command2 = conn.CreateCommand();
command.CommandText = "Insert Into `new` (`Question`, `Answer1`,`Answer2`,`Answer3`,`Answer4`) VALUES ('" + Question + "','" + Option1 + "','" + Option2 + "','" + Option3 + "', '" + Option4.Replace("~", " ") + "')";
conn.Open();
command.ExecuteNonQuery();
conn.Close();
conn.Dispose();
return "Error: Question is unknown, saving the question to get it answered.";
}
}
You have conn.open() in your else statement, and the connection was already opened before that. You should probably consider using the using statement:
using (MySqlConnection conn = new MySqlConnection(connstring))
{
using (MySqlCommand command2 = conn.CreateCommand())
{
}
}

Categories