user3063952
user3063952

Reputation: 97

Stop Nested Try Catch

I have a nested Try/Catch for inventory's ins and outs.

If the Serial number is repeated, the inventory cannot be updated to sum the quantity entered.

Meaning: If I have product "X" with the Serial number "12345" and I enter that, the systems checks if within the "X" products the serial exists.

The first try inserts the serial number, the second try updates inventory.

F/E: I have 7 "X" products, among that 7 products is "12345". If I insert "12345" the first catch indicates that "12345" already exists, but before that updates the inventory and sums +1 to "X" products leaving 8 "X" products when that should not be.

Here's some code:

try
{
  MySqlCommand cmdc = new MySqlCommand( "insert into mov ( folio, clave, descr, total, timo ) VALUES ( '"
    + textBox1.Text
    + "'  ,'"
    + comboBox1.Text
    + "'  ,'"
    + textBox3.Text
    + "'  ,"
    + r1
    + ",'S');" ,
    conn
    ) ;

  MySqlDataAdapter dataadapc = new MySqlDataAdapter(cmdc);
  System.Data.DataTable datatabc = new System.Data.DataTable();
  dataadapc.Fill(datatabc);

  foreach (DataRow row in datatabc.Rows)
  {
    string rows = string.Format("{0}", row.ItemArray[0]);
    aux = rows;
  }

  try
  {
    MySqlCommand command = new MySqlCommand("update inventario SET can = can - "
      + numericUpDown1.Value
      + " WHERE cla = '"
      + comboBox1.Text
      + "';" ,
      conn
      ) ;

    command.ExecuteNonQuery();
    j++;

  }
  catch (Exception ex)
  {
    MessageBox.Show("Error: No se puede modificar el inventario.");
    MessageBox.Show(ex.Message);
  }

  try
  {
    MySqlCommand command = new MySqlCommand("update inventario SET lin = 'CMI', dias = 0 WHERE cla = '"
      + comboBox1.Text
      + "';" ,
      conn
      ) ;

    command.ExecuteNonQuery();

  }
  catch (Exception ex)
  {
    MessageBox.Show("Error: No se puede modificar el inventario.");
    MessageBox.Show(ex.Message);
  }

}
catch (Exception ex)
{
  MessageBox.Show("Error: No se puede modificar el inventario.");
  MessageBox.Show(ex.Message);
}

}

How can I stop the system if the 1st exception activates, so the 2nd query is not executed?

Upvotes: 0

Views: 579

Answers (8)

Reut Sharabani
Reut Sharabani

Reputation: 31339

First off, you should use one try block and one catch block in your program to find and update a product.

That said, your code reveals many possible errors. You should use custom exceptions to navigate program flow after exceptions (not all exceptions should be/are handled the same way).

This means MySqlCommand should throw meaningful exception that explain what the exception was, just like you name variables. For example, you can use name such as ProductNotFoundException and UpdateProductException.

you can do this be extending the class Exception.

For instance, if you try to find the product and that fails, you can use a relevant "catch" clause and react accordingly. If you try to update the product and fail, you can react differently. Finally, a general exception (of type Exception) can be used to spot cases you didn't think of and report to you.

Consider this example:

try{
    // try and find the product
    MySqlCommand.findProduct(serial);
    // if all is well, try and update the product
    // not executed unless findProduct didn't throw an error
    MySqlCommand.updateProduct(serial);
} catch (ProductNotFoundException pnfe){
    // error while finding product
    System.err.println("Product " + serial + " was not found!");
    // .. code to handle product that does not exist
} catch (UpdateProductException upe){
    // error while updating the product
    System.err.println("Product " + serial + " could not be updated!");
    // .. code to handle a failed product update
} catch (Exception e){
    System.err.println("I have no idea why, but something went wrong!");
    e.printStackTrace();
    // handle a general exception
}

MySqlCommand should look more like this:

public class MySqlCommand {

    public void findProduct(int serial) throws ProductNotFoundException{
        // .. code to find product
    }

    public void updateProduct(int serial) throws UpdateProductException{
        // ... code to update product
    }

}

And the ProductNotFoundException class (UpdateProductException is similar):

public class ProductNotFoundException extends Exception {

    public ProductNotFoundException(String message){
        super(message);
    }
}

I also highly recommend reading about SQL Injection and how to prevent it in Java.

Learn more about exceptions, why and how they are used.

Upvotes: 0

CodingMate
CodingMate

Reputation: 343

I think you can define a flag that is initialized in each first try segment, and if an exception popped up in the first Catch, you can set that flag with a value (False for example) and in your second try, check that this flag is not set to the exception value (False)

bool foundException = false;
Try
{
    // Reset the variable in the first Try
    foundException = false;
}
Catch(Exception)
{
    foundException = true;
}
End Try

Try
{
    if(foundException)
    {
        break;
    }
}
Catch(Exception)
{

}

Upvotes: 0

Ivan
Ivan

Reputation: 138

Include 2nd try-catch block into the end of first. This way 2nd block will be executed in case of first is successful.

try
{
  //first

  try
  {
    //secodn
  }
  catch
  {
  }

catch
{
}

Upvotes: 1

David
David

Reputation: 218887

How can I stop the system if the 1st exception activates, so the 2nd query is not executed?

By not using exceptions for control flow in the first place. The conditions you're checking for seem like valid things which could potentially happen. So use simple conditional expressions to check for them. You can nest those conditions accordingly.

So instead of this:

try
{
    InsertID();
}
catch
{
    // nothing exceptional happened
}
try
{
    UpdateInventory();
}
catch
{
    // this is a lot of try/catch for no reason
}

You would do something like this:

if (IDExists())
    HandleIDExistsError();
InsertID();
UpdateInventory();

Or perhaps this:

if (!IDExists())
{
    InsertID();
    UpdateInventory();
}

Looking back at your updated question, you have a lot of try/catch blocks which are just handling logic flow. The catch blocks are making assumptions about the nature of the error that occurred, which may be incorrect. And then they're throwing away useful information about the exception, which can be used to correct the problem.

Exceptions aren't for normal logic flow. Don't use them in place of conditionals.

Edit: Better yet, look into using transactions. Since you have two data modifications which should happen as a single atomic process, you might wrap that in an exception handler. Something like:

if (!IDExists())
{
    try
    {
        BeginTransaction();
        InsertID();
        UpdateInventory();
        CommitTransaction();
    }
    catch
    {
        HandleError();
        RollBackTransaction();
    }
}

Upvotes: 0

Odrai
Odrai

Reputation: 2353

Put a "return" in the catch, so that any code that follows will not be executed.

try
{
    // Do something
}
catch
{
    // Do something
    return;
}

Upvotes: 0

Dialecticus
Dialecticus

Reputation: 16761

Put both actions in one try block

try
{
    MySqlCommand command = new MySqlCommand("update inventario SET can = can - " + numericUpDown1.Value + " WHERE cla = '" + comboBox1.Text + "';", conn);
    command.ExecuteNonQuery();
    j++;

    MySqlCommand command = new MySqlCommand("update inventario SET lin = 'CMI', dias = 0 WHERE cla = '" + comboBox1.Text + "';", conn);
    command.ExecuteNonQuery();
}
catch (Exception ex)
{
    MessageBox.Show("Error: No se puede modificar el inventario.");
    MessageBox.Show(ex.Message);
}

Upvotes: 4

mrK
mrK

Reputation: 2288

Can you do something like this:

try{

    try{
        // insert serial number
    }

    catch{
         //handle exception
        throw;
    }

    try{
        // update inventory
    }
    catch{
        // handle inventory exception
    }

}
catch{
    // handle other exceptions
}

Upvotes: 0

Haedrian
Haedrian

Reputation: 4328

From your description, I'm assuming you want an exception to keep travelling upwards.

You can do that by throwing the exception again

    catch (Exception ex)
    {
      //Log the error or whatever
    throw;
    }

This will toss the exception upwards, and your second part of the code won't be executed.

Upvotes: 0

Related Questions