即使出现错误信息,存储过程仍在执行

时间:2018-07-24 23:34:38

标签: asp.net stored-procedures

我正在使用ASP.NET按钮功能中的两个存储过程。虽然我收到的结果是错误消息,表明发票号已经从其他存储过程中分派了,但它仍然移至其他存储过程并执行。

如果用户收到此错误消息:

  

此发票编号已经发送!

那么它就不应继续涉及该功能

protected void Button2_Click(object sender, EventArgs e)
{
    try
    {
        for (int i = GridView2.Rows.Count - 1; i >= 0; i--)
        {
            var row = GridView2.Rows[i];

            CheckBox chk = row.FindControl("chkInvoice") as CheckBox;
            //CheckBox chk = (CheckBox)GridView2.Rows[i].Cells[0].FindControl("CheckBox3");

            if (chk != null && chk.Checked)
            {
                string strSQLconstring = System.Configuration.ConfigurationManager.ConnectionStrings["TWCL_OPERATIONSConnectionString"].ToString();

                using (SqlConnection objConnection = new SqlConnection(strSQLconstring))
                {
                    objConnection.Open();

                    using (SqlTransaction transaction = objConnection.BeginTransaction())
                    {
                        string SID = GridView2.Rows[i].Cells[3].Text.Trim();
                        SqlDataReader myReader = null;

                        using (SqlCommand command = new SqlCommand("PP_SelectStatus", objConnection, transaction))
                        {
                            command.CommandType = CommandType.StoredProcedure;

                            command.Parameters.AddWithValue("@invoiceNum", SID);
                            command.Parameters.AddWithValue("@custPONum", GridView2.Rows[i].Cells[4].Text.Trim());

                            myReader = command.ExecuteReader();

                            if (myReader.Read())
                            {
                                string invoice1 = (myReader["status"].ToString());
                                if (invoice1 == "0")
                                {
                                    ClientScript.RegisterClientScriptBlock(this.GetType(), "alert", "alert('This invoice num was already dispatched!')", true);
                                }

                                myReader.Close();
                            }
                        }
                        else if (invoice1=="1")
                        {
                            using (SqlCommand cmd = new SqlCommand("PP_RemoveInvoice", objConnection, transaction))
                            {
                                cmd.CommandType = CommandType.StoredProcedure;

                            cmd.Parameters.AddWithValue("@loadSheetNum", txtDispatchNum.Text);
                            cmd.Parameters.AddWithValue("@invoiceNum", SID);
                            cmd.Parameters.AddWithValue("@removeUser", lblUsername.Text.Replace("Welcome", ""));

                            **int a = cmd.ExecuteNonQuery();**

                            cmd.Dispose();

                            if (a > 0)
                            {
                                dt.Rows.RemoveAt(i);

                                ////Read invoice qty from grid view 2
                                string invoice = GridView2.Rows[i].Cells[5].Text.ToString();
                                decimal invoiceTotal = Convert.ToDecimal(txtInvoiceTotal.Text) - Convert.ToDecimal(invoice);
                                txtInvoiceTotal.Text = invoiceTotal.ToString();

                                ////Read invoice weight from grid view 2
                                string weight = GridView2.Rows[i].Cells[6].Text.ToString();
                                decimal invoiceWeight = Convert.ToDecimal(txtQtyWeight.Text) - Convert.ToDecimal(weight);
                                txtQtyWeight.Text = invoiceWeight.ToString();
                                lblError.ForeColor = Color.Green;

                                lblError.Text = "Selected record(s) successfully updated";
                            }
                            else
                            {
                                lblError.ForeColor = Color.Red;
                                lblError.Text = " Record has not yet been recorded";
                            }
                        }

                        //objConnection.Close();
                        transaction.Commit();
                    }
                  }
                }

                //Button2.Visible = false;
                //showData();
                GridView2.DataSource = dt;
                GridView2.DataBind();

                txtInvoiceCount.Text = dt.Rows.Count.ToString();
            }
        }
    }
    catch (Exception ex)
    {
        if (ex.Message.StartsWith("Violation of PRIMARY KEY constraint"))
        {
            lblError.ForeColor = Color.Red;
            lblError.Text = " This invoice number was remove from dispatch sheet before!!";
        }
        else
        {
            // re-throw the error if you haven't handled it
            lblError.Text = ex.Message;
            throw;
        }
    }
}

2 个答案:

答案 0 :(得分:1)

您有一个非常非常简单的逻辑错误,但是很难看到,因为您的代码太乱了。因此,我的答案是:

REFACTOR REFACTOR REFACTOR

养成编写短函数并控制其输入和输出的习惯非常重要。如果您不这样做,那么像这样的琐碎操作也将变得非常混乱和容易出错。

这里是如何组织事物的示例。我们从点击处理程序中删除了大部分代码:

protected void DeleteButton_Click(object sender, EventArgs e)
{
    for (int i = GridView2.Rows.Count - 1; i >= 0; i--)
    {
        var row = GridView2.Rows[i];
        if (IsChecked(row))
        {
            var result = ProcessRow(row, i);
            DisplayResult(i, result);
        }
    }
}

首先,请注意它的名称有意义。随着应用程序的增长,这些变得非常重要。另外,看它有多短!所有代码都去了哪里?好了,它分为两种独立的方法,现在它们足够短,我们可以在一页上查看,这是IT组织强加给程序员的一个通用要求,以避免产生意粉代码。

protected TransactionResult ProcessRow(GridViewRow row, int index)
{
    var SID = GridView2.Rows[index].Cells[3].Text.Trim();
    var custPONum = GridView2.Rows[index].Cells[4].Text.Trim();
    var loadSheetNum = txtDispatchNum.Text;
    var removeUser = lblUsername.Text.Replace("Welcome", "");

    return ExecuteInvoiceTransaction(SID, custPONum, loadSheetNum, removeUser);
}

public void DisplayResult(int rowIndex, TransactionResult result)
{
    switch result
    {
        case TransactionResult.Success:
            dt.Rows.RemoveAt(rowIndex);
            DisplayTotals(rowIndex);
            DisplaySuccess("Selected record(s) successfully updated");
            break;

        case TransactionResult.AlreadyDispatched;
            ClientScript.RegisterClientScriptBlock(this.GetType(), "alert", "alert('This invoice num was already dispatched!')", true);
            break;

        case TransactionResult.RecordNotRecorded;
            DisplayError("Record has not yet been recorded");
            break;

        case TransactionResult.AlreadyRemoved:
            DisplayError("This invoice number was remove from dispatch sheet before!!");
            break;
    }
}

这些方法依次调用各种帮助程序方法,每个方法仅执行一项操作,而仅执行一项操作。这可以称为separation of concerns,它对结构化代码非常重要。

以下是其余方法:

enum TransactionResult
{
    Success,
    AlreadyDispatched,
    RecordNotRecorded,
    AlreadyRemoved
}

private bool ExecuteSelectStatus(SqlConnection connection, SqlTransaction transaction, string invoiceNum, string custPONum)
{
    using (SqlCommand command = new SqlCommand("PP_SelectStatus", objConnection, transaction))
    {
        command.CommandType = CommandType.StoredProcedure;
        command.Parameters.AddWithValue("@invoiceNum", invoiceNum);
        command.Parameters.AddWithValue("@custPONum", custPONum);
        using (var myReader = command.ExecuteReader())
        {
            if (myReader.Read())
            {
                string invoice1 = (myReader["status"].ToString());
                if (invoice1 == "0")
                {
                    return false;
                }
            }
        }
        return true;
    }
}

private int ExecuteRemoveInvoice(SqlConnection objConnection, SqlTransaction transaction, string loadSheetNum, string invoiceNum, string removeUser)
{
    try
    {
        using (SqlCommand cmd = new SqlCommand("PP_RemoveInvoice", objConnection, transaction))
        {
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.AddWithValue("@loadSheetNum", loadSheetNum);
            cmd.Parameters.AddWithValue("@invoiceNum", invoiceNum);
            cmd.Parameters.AddWithValue("@removeUser", removeUser);
            return cmd.ExecuteNonQuery();
        }
    }
    catch (SqlException ex)
    {
        if (ex.Number == 2627) //Primary key violation
        {
            return -1;
        }
    }
}

protected TransactionResult ExecuteInvoiceTransaction(string invoiceNum, string custPONum, string loadSheetNum, string removeUser)
{
    var strSQLconstring = System.Configuration.ConfigurationManager.ConnectionStrings["TWCL_OPERATIONSConnectionString"].ToString();

    using (SqlConnection objConnection = new SqlConnection(strSQLconstring))
    {
        objConnection.Open();

        using (SqlTransaction transaction = objConnection.BeginTransaction())
        {
            var ok = ExecuteSelectStatus(objConnection, transaction, invoiceNum, custPONum);
            if (!ok) return TransactionResult.AlreadyDispatched;

            var a = ExecuteRemoveInvoice(objConnection, transaction, loadSheetNum, invoiceNum, removeUser);
            switch a
            {
                case -1: 
                    return TransactionResult.AlreadyRemoved;
                case 0:
                    return TransactionResult.RecordNotRecorded;
                default:
                    transaction.Commit();
                    return TransactionResult.Success;
            }
        }
    }
}

public void DisplayTotals(int i)
{
    ////Read invoice qty from grid view 2
    string invoice = GridView2.Rows[i].Cells[5].Text;
    decimal invoiceTotal = Convert.ToDecimal(txtInvoiceTotal.Text) - Convert.ToDecimal(invoice);
    txtInvoiceTotal.Text = invoiceTotal.ToString();

    ////Read invoice weight from grid view 2
    string weight = GridView2.Rows[i].Cells[6].Text();
    decimal invoiceWeight = Convert.ToDecimal(txtQtyWeight.Text) - Convert.ToDecimal(weight);
    txtQtyWeight.Text = invoiceWeight.ToString();
}

public void DisplaySuccess(string message)
{
    lblError.ForeColor = Color.Green;
    lblError.Text = message;
}

public void DisplayError(string message)
{
    lblError.ForeColor = Color.Red;
    lblError.Text = message;
}

一些注意事项:

  • 如果您使用的是Dispose(),则无需致电using
  • 您应始终按照Microsoft's guidance捕获最具体的异常。我的例子做到了。
  • 主键错误的异常处理被隔离到调用存储过程的方法中。总体业务逻辑不必知道有关SQL实现的详细信息。我已经展示了如何根据this post来识别特定错误。
  • 由于可能有四种结果,因此我添加了一个名为TransactionResult的枚举,以便我们可以轻松地将状态返回给调用方。
  • 其中一些方法很短-只有两行-没关系。区分它们的主要原因是给它们起一个有意义的名称,并使代码更短,更易于阅读。
  • 此代码的结构更加丰富,但仍可以改进!在许多实现中,访问数据库的代码实际上被移到了完全不同的层或项目中。

答案 1 :(得分:0)

查看是否可行。将您的if / else一起移动:

protected void Button2_Click(object sender, EventArgs e)
    {
        try
        {
            for (int i = GridView2.Rows.Count - 1; i >= 0; i--)
            {
                var row = GridView2.Rows[i];

                CheckBox chk = row.FindControl("chkInvoice") as CheckBox;

                if (chk != null && chk.Checked)
                {
                    string strSQLconstring = System.Configuration.ConfigurationManager.ConnectionStrings["TWCL_OPERATIONSConnectionString"].ToString();

                    using (SqlConnection objConnection = new SqlConnection(strSQLconstring))
                    {
                        objConnection.Open();

                        using (SqlTransaction transaction = objConnection.BeginTransaction())
                        {
                            string SID = GridView2.Rows[i].Cells[3].Text.Trim();
                            SqlDataReader myReader = null;
                            using (SqlCommand command = new SqlCommand("PP_SelectStatus", objConnection, transaction))
                            {

                                command.CommandType = CommandType.StoredProcedure;

                                command.Parameters.AddWithValue("@invoiceNum", SID);
                                command.Parameters.AddWithValue("@custPONum", GridView2.Rows[i].Cells[4].Text.Trim());
                                myReader = command.ExecuteReader();

                                if (myReader.Read())
                                {

                                    string invoice1 = (myReader["status"].ToString());
                                    if (invoice1 == "0")
                                    {
                                        ClientScript.RegisterClientScriptBlock(this.GetType(), "alert", "alert('This invoice num was already dispatched!')", true);
                                    }

                                    else if (invoice1 == "1")
                                    {
                                        using (SqlCommand cmd = new SqlCommand("PP_RemoveInvoice", objConnection, transaction))
                                        {
                                            cmd.CommandType = CommandType.StoredProcedure;

                                            cmd.Parameters.AddWithValue("@loadSheetNum", txtDispatchNum.Text);
                                            cmd.Parameters.AddWithValue("@invoiceNum", SID);
                                            cmd.Parameters.AddWithValue("@removeUser", lblUsername.Text.Replace("Welcome", ""));

                                            int a = cmd.ExecuteNonQuery();
                                            cmd.Dispose();

                                            if (a > 0)
                                            {
                                                dt.Rows.RemoveAt(i);

                                                ////Read invoice qty from grid view 2
                                                string invoice = GridView2.Rows[i].Cells[5].Text.ToString();
                                                decimal invoiceTotal = Convert.ToDecimal(txtInvoiceTotal.Text) - Convert.ToDecimal(invoice);
                                                txtInvoiceTotal.Text = invoiceTotal.ToString();

                                                ////Read invoice weight from grid view 2
                                                string weight = GridView2.Rows[i].Cells[6].Text.ToString();
                                                decimal invoiceWeight = Convert.ToDecimal(txtQtyWeight.Text) - Convert.ToDecimal(weight);
                                                txtQtyWeight.Text = invoiceWeight.ToString();
                                                lblError.ForeColor = Color.Green;

                                                lblError.Text = "Selected record(s) successfully updated";
                                            }
                                            else
                                            {
                                                lblError.ForeColor = Color.Red;
                                                lblError.Text = " Record has not yet been recorded";
                                            }
                                        }
                                        //objConnection.Close();
                                        transaction.Commit();
                                    }


                                }
                            }

                            GridView2.DataSource = dt;
                            GridView2.DataBind();
                            txtInvoiceCount.Text = dt.Rows.Count.ToString();
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            if (ex.Message.StartsWith("Violation of PRIMARY KEY constraint"))
            {
                lblError.ForeColor = Color.Red;
                lblError.Text = " This invoice number was remove from dispatch sheet before!!";
            }
            else
            {
                // re-throw the error if you haven't handled it
                lblError.Text = ex.Message;
                throw;

            }
        }
    }

}