I ask if the following code need some refactoring :public static int InsertBonus(DataTable dt, int month, int year){    int affectedRow = -1;    using (IfxConnection con = new IfxConnection(ConfigurationManager.ConnectionStrings[xxx].ToString()))    {        using (IfxTransaction tran = con.BeginTransaction())        {            try            {                StringBuilder cmdTxt = new StringBuilder();                cmdTxt.Append( DELETE FROM rh7uiw WHERE bonus_mon = ? AND bonus_year = ? );                using (var myIfxCmd = new IfxCommand(cmdTxt.ToString(), con))                {                    myIfxCmd.CommandType = CommandType.Text;                    myIfxCmd.Parameters.Add(bonus_mon, IfxType.Integer);                    myIfxCmd.Parameters.Add(bonus_year, IfxType.Integer);                    if (con.State == ConnectionState.Closed)                    {                        con.Open();                    }                    myIfxCmd.Parameters[0].Value = ((object)month) ?? DBNull.Value;                    myIfxCmd.Parameters[1].Value = ((object)year) ?? DBNull.Value;                    affectedRow = myIfxCmd.ExecuteNonQuery();                }                cmdTxt.Length = 0;                cmdTxt.Append( INSERT INTO rh7uiw (emp_num,bonus_year,bonus_mon,bonus_value,bonus_no,rr_code) VALUES(?,?,?,?,?,?) );                using (var myIfxCmd = new IfxCommand(cmdTxt.ToString(), con))                {                    myIfxCmd.CommandType = CommandType.Text;                    myIfxCmd.Parameters.Add(emp_num, IfxType.Integer);                    myIfxCmd.Parameters.Add(bonus_year, IfxType.Integer);                    myIfxCmd.Parameters.Add(bonus_mon, IfxType.Integer);                    myIfxCmd.Parameters.Add(bonus_value, IfxType.Integer);                    myIfxCmd.Parameters.Add(bonus_no, IfxType.Integer);                    myIfxCmd.Parameters.Add(rr_code, IfxType.Integer);                    foreach (DataRow r in dt.Rows)                    {                        if (con.State == ConnectionState.Closed)                        {                            con.Open();                        }                        myIfxCmd.Parameters[0].Value = (r[emp_num]) ?? DBNull.Value;                        myIfxCmd.Parameters[1].Value = (r[year]) ?? DBNull.Value;                        myIfxCmd.Parameters[2].Value = (r[month]) ?? DBNull.Value;                        myIfxCmd.Parameters[3].Value = (r[bonus_al]) ?? DBNull.Value;                        myIfxCmd.Parameters[4].Value = 1;                        myIfxCmd.Parameters[5].Value = 1;                        affectedRow = myIfxCmd.ExecuteNonQuery();                    }                }                tran.Commit();                con.Close();                con.Dispose();                return affectedRow;            }            catch            {                tran.Rollback();                throw;            }        }    }}
simple transaction process
c#;asp.net
Yes:You don't need to use a StringBuilder when you are not building a string. Just use the string.Don't check the state of the connection for every query. Just open the connection before the first query, and it stays open.The check for null for month and year in the first query is not needed. An int can not be null.As you are creating the connection in a using block, you don't need to close and dispose it. The using block will do that for you.Returning affectedRow from the method seems pointless, as it only contains how many records the last query affected.