Maybe this is not the best source I've ever written but it is for a simple form that has the goal to write data remotely. I've two MySQLConnections both for a local database. localconnection is used to read the DB and updateconnection edit every single row. The problem is that when i'm trying to update the Database the program raise a timeout and it crash. I think the problem is generated by the while loop. My intention is to read a single row, post it on the server and update it if the server returns the status equals 200.
Here's the code, it fails on updateConnection.ExcecuteNonQuery();
// Local Database here.
localCommand.Parameters.Clear();
// 0 - Grab unsent emails
string receivedMessages = "SELECT * FROM EMAIL WHERE HASSENT = 0";
// Update connection init START
string updateConnectionString = "Server=" + this.localServer + ";Database=" + this.localDatabase + ";Uid=" + this.localUser + ";Pwd=" + this.localpassword;
MySqlConnection updateConnection = new MySqlConnection(updateConnectionString);
updateConnection.Open();
MySqlTransaction transaction = updateConnection.BeginTransaction();
MySqlCommand updateCommand = new MySqlCommand();
// Update connection init END
localCommand.Connection = localConnection;
localCommand.Prepare();
try
{
localCommand.CommandText = receivedMessages;
MySqlDataReader reader = localCommand.ExecuteReader();
while (reader.Read()) // Local db read
{
String EID = reader.GetString(0);
String message = reader.GetString(3);
String fromEmail = reader.GetString(6);
String toEmail= reader.GetString(12);
// 1 - Post Request via HttpWebRequest
var receivedResponse = JObject.Parse(toSend.setIsReceived(fromEmail, message, toEmail));
// 2 - Read the JSON response from the server
if ((int)receivedResponse["status"] == 200)
{
string updateInbox = "UPDATE EMAIL SET HASSENT = 1 WHERE EMAILID = @EID";
MySqlParameter EMAILID = new MySqlParameter("@EID", MySqlDbType.String);
EMAILID.Value = EID; // We use the same fetched above
updateCommand.Connection = updateConnection;
updateCommand.Parameters.Add(IID_value);
updateCommand.Prepare();
updateCommand.CommandText = updateInbox;
updateCommand.ExecuteNonQuery();
}
else
{
// Notice the error....
}
}
}
catch (MySqlException ex)
{
transaction.Rollback();
// Notice...
}
finally
{
updateConnection.Close();
}
It is hard to tell exactly what's wrong here without doing some experiments.
There are two possibilities, though.
First, your program appears to be running on a web server, which necessarily constrains it to run for a limited amount of time. But, you loop through a possibly large result set, and do stuff of an uncontrollable duration for each item in that result set.
Second, you read a result set row by row from the MySQL server, and with a different connection try to update the tables behind that result set. This may cause a deadlock, in which the MySQL server blocks one of your update queries until the select query completes, thus preventing the completion of the select query.
How to cure this? First of all, try to handle a fixed and small number of rows in each invocation of this code. Change your select query to
SELECT * FROM EMAIL WHERE HASSENT = 0 LIMIT 10
and you'll handle ten records each time through.
Second, read in the whole result set from the select query, into a data structure, then loop over the items. In other words, don't nest the updates in the select.
Third, reduce the amount of data you handle by changing SELECT *
to SELECT field, field, field
.