If you haven't taken a look at the solution to the last bug, please do so. There were 4 bugs in that short chink of code -- all of which are found in Visual Studio 2005! One is issued as a compiler warning and the other 3 are found by PREfast.

Here is the next "Spot the Bug." This one is certainly more lengthy and complex than the last. There were some typos in the original post which were fixed.
Courtesy of Shanit Gupta, Consultant (Foundstone)

private void TransferFunds ()
{
...
 if (fromaccount.balance  > amount) {
  fromaccount.balance -= amount;
  toaccount.balance += amount; 
 }
...
}

private void RetrieveAccountInfo (int payer, int payee)
{
...
...
...
fromAccount = RetrieveFundInfo(myConnection, payer);
toAccount = RetrieveFundInfo(myConnection, payee);
TransferFunds();
CommitChanges (fromAccount.number, fromAccount.balance);
CommitChanges (toAccount.number, toAccount.balance);
}

private int RetrieveFundInfo (SqlConnection myConnection, int accountNumber)
{
 string mySelectQuery = "SELECT balance FROM Customers where accountnumber = " + “’” + accountNumber + “’”;
 SqlCommand myCommand = new SqlCommand(mySelectQuery,myConnection);
 SqlDataReader myReader = myCommand.ExecuteReader();
 return myReader.GetInt32(0);
}

private void CommitChanges (int accountNumber, int balance);
{
 string mySelectQuery = "UPDATE Customers Set Balance = “ + “’” + balance + “’”  + “where AccountNumber = " + “’” + accountNumber + “’”;
 SqlCommand myCommand = new SqlCommand(mySelectQuery,myConnection);
 myCommand.ExecuteNonQuery();
}

Suggested Implementation:

private void TransferFunds ()

{

..

      if (fromaccount.balance  > amount) {

            fromaccount.balance -= amount;

            toaccount.balance += amount; 

      }

}

 

private void RetrieveAccountInfo (int payer, int payee)

{

...

...

...

SqlTransaction myTrans;

myTrans = myConnection.BeginTransaction("SampleTransaction");

  try

    {

 

fromAccount = RetrieveFundInfo(myConnection, payer);

toAccount = RetrieveFundInfo(myConnection, payee);

TransferFunds();

CommitChanges (fromAccount.number, fromAccount.balance);

      CommitChanges (toAccount.number, toAccount.balance);

      myTrans.Commit();

 

}

catch(Exception e)

    {

      try

      {

        myTrans.Rollback("SampleTransaction");

      }

      catch (SqlException ex)

      {

        if (myTrans.Connection != null)

        {

          Console.WriteLine("An exception of type " + ex.GetType() +

                            " was encountered while attempting to roll back the transaction.");

        }

      }

   

      Console.WriteLine("An exception of type " + e.GetType() +

                        " was encountered while inserting the data.");

      Console.WriteLine("Neither record was written to database.");

    }

    finally

    {

      myConnection.Close();

    }

}

 

 

private int RetrieveFundInfo (SqlConnection myConnection, int accountNumber)

{

      string mySelectQuery = "SELECT balance FROM Customers where accountnumber = " + “’” + accountNumber + “’”;

      SqlCommand myCommand = new SqlCommand(mySelectQuery,myConnection);

      SqlDataReader myReader = myCommand.ExecuteReader();

      Return myReader.GetInt32(0);

}

 

private void CommitChanges (int accountNumber, int balance);

{

        string mySelectQuery = "UPDATE Customers Set Balance = “ + “’” + balance + “’”  + “where AccountNumber = " + “’” + accountNumber + “’”;
        SqlCommand myCommand = new SqlCommand(mySelectQuery,myConnection);
        myCommand.ExecuteNonQuery();

}

 

 

Description: Race conditions happen in a multi-threaded (process) environment where there is a window of vulnerability for state corruption and compromise. The condition occurs owing to the fact that the information read is different from information processed, which leaves the state inconsistent or incorrect. One way to avoid this possibility is by gaining exclusive locks on the rows that are being read and updated. The suggested code uses “SqlTransaction myTrans” which locks the rows for isolation property of the transaction.