0

So I've been used to coding with try-catch-finally statements and not including the using statement and I'm trying to incorporate the latter into my code.

I've attached my original and revised code below. Is this revision sufficient?

Also, regarding catching for errors, I've seen the following code used a number of times on here. When should this be used/not used since this doesn't inform users about the error?

catch (Exception ex)
{
    throw ex;
}

original code:

protected void signIn()
{
    string connStr = ConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString;
    MySqlConnection conn = new MySqlConnection(connStr);

    MySqlCommand comm;
    comm = new MySqlCommand("Select user_id, username, email, salt, hashed_pw, role, activated FROM users WHERE username=@username", conn);
    comm.Parameters.Add("@username", MySqlDbType.VarChar);
    comm.Parameters["@username"].Value = txtUsername.Text;
    MySqlDataReader reader;

    try
    {
        conn.Open();
        reader = comm.ExecuteReader();

        if (reader.Read())
        {
            string saltAndPwd = String.Concat(txtPassword.Text, reader["salt"].ToString());
            string hashSaltAndPwd = FormsAuthentication.HashPasswordForStoringInConfigFile(saltAndPwd, "sha1");

            if (hashSaltAndPwd.Equals(reader["hashed_pw"].ToString()))
            {
                if (reader["activated"].ToString().Equals("Y"))
                {
                    Session["Username"] = reader["username"].ToString();
                    Session["Role"] = reader["role"].ToString();
                    Session["UserID"] = reader["user_id"].ToString();
                    Session["EmailAddress"] = reader["email"].ToString();

                    if (reader["role"].ToString().Equals("0"))
                    {
                        Session["PermanentRole"] = "admin";
                    }
                    else if (reader["role"].ToString().Equals("2"))
                    {
                        Session["PermanentRole"] = "tutor";
                    }

                    Response.Redirect("~/portal.aspx");
                }
                else
                {
                    lblError.Text = "Your account has not been activated.  Please check your inbox and activate your account or reset your password by clicking the link above.";
                }
            }
            else
            {
                lblError.Text = "Incorrect password.";
            }
        }
        else
        {
            lblError.Text = "Username does not exist.";
        }

        reader.Close();
    }
    catch
    {
        lblError.Text = "Database connection error. Please try again.";
    }
    finally
    {
        conn.Close();
    }
}

revised code:

protected void signIn()
{
    string connStr = ConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString;

    using (MySqlConnection conn = new MySqlConnection(connStr))
    {
        using (MySqlCommand cmd = conn.CreateCommand())
        {
            string cmdText = "Select user_id, username, email, salt, hashed_pw, role, activated FROM users WHERE username=@username";
            cmd.CommandText = cmdText;
            cmd.Parameters.Add("@username", MySqlDbType.VarChar);
            cmd.Parameters["@username"].Value = txtUsername.Text;

            try
            {
                conn.Open();
                reader = cmd.ExecuteReader();

                if (reader.Read())
                {
                    string saltAndPwd = String.Concat(txtPassword.Text, reader["salt"].ToString());
                    string hashSaltAndPwd = FormsAuthentication.HashPasswordForStoringInConfigFile(saltAndPwd, "sha1");

                    if (hashSaltAndPwd.Equals(reader["hashed_pw"].ToString()))
                    {
                        if (reader["activated"].ToString().Equals("Y"))
                        {
                            Session["Username"] = reader["username"].ToString();
                            Session["Role"] = reader["role"].ToString();
                            Session["UserID"] = reader["user_id"].ToString();
                            Session["EmailAddress"] = reader["email"].ToString();

                            if (reader["role"].ToString().Equals("0"))
                            {
                                Session["PermanentRole"] = "admin";
                            }
                            else if (reader["role"].ToString().Equals("2"))
                            {
                                Session["PermanentRole"] = "tutor";
                            }

                            Response.Redirect("~/portal.aspx");
                        }
                        else
                        {
                            lblError.Text = "Your account has not been activated.  Please check your inbox and activate your account or reset your password by clicking the link above.";
                        }
                    }
                    else
                    {
                        lblError.Text = "Incorrect password.";
                    }
                }
                else
                {
                    lblError.Text = "Username does not exist.";
                }

                reader.Close();
            }
            catch
            {
                lblError.Text = "Database connection error. Please try again.";
            }
            finally
            {
                conn.Close();
            }
        }
    }
Bhav
  • 1,957
  • 7
  • 33
  • 66
  • 2
    _"ive seen the following code used a number of times on here. When should this be used/not used since this doesn't inform users about the error?"_ No, never, where have you seen it? Don't do `throw ex` in an empty `Catch`. Read http://stackoverflow.com/questions/1234343/why-are-empty-catch-blocks-a-bad-idea and http://stackoverflow.com/questions/730250/is-there-a-difference-between-throw-and-throw-ex – Tim Schmelter Aug 07 '14 at 13:16
  • You don't need to close the connection, the `using` block will handle that for you (well, technically the dispose method of the connection class) – musefan Aug 07 '14 at 13:16
  • `"When should this be used?"` - Never. `throw ex;` should never be used like that. It's throwing away useful stack trace information. If all you need to do is re-throw the same exception, use `throw;`. If all you're doing *at all* is re-throwing the same exception, omit the `catch` block entirely because it's not doing anything. – David Aug 07 '14 at 13:19

2 Answers2

2

1) conn.Close(); is not necessary since the using statement will call close for you. It is equivalent to

MySqlConnection conn = new MySqlConnection(connStr)
try
{
     ....
}
finally
{
    conn.Close();
}

2) The catch with the form

catch (Exception ex)
{
    throw ex;
}

is not recommended in any situation I can think of. It has 2 problems

  • It's doing nothing except rethrowing the exception. You don't catch the exception unless you want to do something with it (e.g.: logging the error)

  • Rethrowing the exception doing throw ex; cuts the stack trace. Anyone catching that exception will see the error as generated on that line, losing useful information

Claudio Redi
  • 67,454
  • 15
  • 130
  • 155
1

You don't need the finally { ...} because the using will Dispose the connection.

Your question about:

catch (Exception ex)
{
  throw ex;
}

Is common when you want to Log the exception but still throw it, simply catching and re-throwing serves no purpose.

But should be done like this:

catch (Exception ex)
{
  LogManager.Log(ex);
  throw;  //rethrow
}
T McKeown
  • 12,971
  • 1
  • 25
  • 32