Question

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();
   }
Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top