我如何在c#的消息框中显示错误消息,SQL异常(唯一标识符)在3层应用程序中

本文关键字:消息 唯一 异常 标识符 应用程序 3层 SQL 显示 错误 | 更新日期: 2023-09-27 18:04:14

我正在使用c#和SQL设计一个windows窗体三层应用程序。我设计了用户注册页面,该页面使用存储过程与数据库连接。我已经把文本框从用户输入。我对用户名列使用了唯一约束。因为我使用3层应用程序架构,所以我已经把我的register_user函数在BLL和调用它从按钮在UI。当我在文本框中输入重复的用户名时,它会抛出一个异常(如预期的那样)的唯一约束,但我希望的是,这条消息应该显示在一个窗口框中,我的应用程序不应该停止工作。我试过在register_user函数中使用try catch,但它没有用。同样,我也尝试在我的UI(注册按钮)中使用try catch,但再次失败。我在这里张贴我的代码:由于

//BLL

    public void register_user(string First_Name,string Last_Name,string User_Name,string Password,string Date_Of_Birth,string Security_Question,string Security_Answer)
    {
        try
        {
            DAL obj = new DAL();
            obj.OpenConnection();
            obj.LoadSpParameters("UR", First_Name, Last_Name, User_Name, Password, Date_Of_Birth, Security_Question, Security_Answer);
            obj.ExecuteQuery();
            obj.UnLoadSpParameters();
        }
        catch (SqlException ex)
        {
            MessageBox.Show(ex.ToString());
        }
        finally
        {
            DAL obj2 = new DAL();
            obj2.CloseConnection();
        }   
       } 
UI

//

    private void register_button_Click(object sender, EventArgs e)
    {
        if (first_name_text.Text == "" || last_name_text.Text == "" || user_name_text.Text == "" || password_text.Text == "" || confirm_password_text.Text == "" || answer_txt.Text == "")
        {
            alert1_label.Show();
            error1_label.Show();
            error1_label.Text = "You cannot left mandatory fields empty";
        }
        if (password_text.Text.Length <= 8)
        {
            alert1_label.Show();
            error1_label.Show();
            error1_label.Text = "Password must be greater than 8 characters";
            password_text.Clear();
            confirm_password_text.Clear();
            return;

        }
        if (first_name_text.Text.Any(Char.IsDigit) || first_name_text.Text.Any(Char.IsPunctuation) || first_name_text.Text.Any(Char.IsSeparator) || first_name_text.Text.Any(Char.IsSymbol))
        {
            alert1_label.Show();
            error1_label.Show();
            error1_label.Text = "Numbers and Special Characters are not allowed in first name";
            first_name_text.Clear();
            return;
        }
        if (last_name_text.Text.Any(Char.IsDigit) || last_name_text.Text.Any(Char.IsPunctuation) || last_name_text.Text.Any(Char.IsSeparator) || last_name_text.Text.Any(Char.IsSymbol))
        {
            alert1_label.Show();
            error1_label.Show();
            error1_label.Text = "Numbers and Special Characters are not allowed in last name";
            last_name_text.Clear();
            return;
        }
        if (!user_name_text.Text.Any(Char.IsLetter))
        {
            alert1_label.Show();
            error1_label.Show();
            error1_label.Text = "User Name must contain atleast one alphabet, and must be atleast 4 characters long.";
            user_name_text.Clear();
            return;
        }
        if (user_name_text.Text.Length <= 3)
        {
            alert1_label.Show();
            error1_label.Show();
            error1_label.Text = "User Name must contain atleast one alphabet, and must be atleast 4 characters long.";
            user_name_text.Clear();
            return;
        }
        else
        {
           try
           {
            error1_label.Hide();
            alert1_label.Hide();
            BLL obj = new BLL();
            obj.register_user(first_name_text.Text, last_name_text.Text, user_name_text.Text, password_text.Text, date_of_birth_text.Text, security_question_text.SelectedItem.ToString(), answer_txt.Text);
                MessageBox.Show("Registration Successful");
                UP frm = new UP();
                frm.Text = "Welcome" + " " + first_name_text.Text;
                this.Dispose();
                frm.Show();
            }
            catch(SqlException ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }

我如何在c#的消息框中显示错误消息,SQL异常(唯一标识符)在3层应用程序中

您的BLL中的一个问题是关闭未打开的连接。在你的register_user方法中,你有一个finally块,它创建了一个new DAL()对象,然后你调用CloseConnection

没有看到这个实现,我怀疑您想要关闭在try块中创建的DAL对象。如果是这种情况,一种可能的修复方法是将obj变量提升到try块之外,以便它在try和finally块中可用。

请记住,变量在c#中有块作用域。

public void register_user(string First_Name,string Last_Name,string User_Name,string Password,string Date_Of_Birth,string Security_Question,string Security_Answer)
{ 
    DAL obj = null; // initialize to a value
    try
    {
        obj = new DAL();
        obj.OpenConnection();
        obj.LoadSpParameters("UR", First_Name, Last_Name, User_Name, Password, Date_Of_Birth, Security_Question, Security_Answer);
        obj.ExecuteQuery();
        obj.UnLoadSpParameters();
    }
    catch (SqlException ex)
    {
        MessageBox.Show(ex.ToString());
    }
    finally
    {
        if (obj!=null)  // check for null in case the constructor did throw an exception
        {
          obj = new DAL();
          obj.CloseConnection();
        } 
        else
        {
            Debug.Assert(obj!=null, "DAL not intialized");
        }
    }   
   } 

超出了这个答案的范围,您必须重新考虑捕获异常的原因和时间。作为一般规则,只有知道如何处理异常,才能捕获异常。在当前的代码示例中,BLL和UI层都处理异常。如果操作得当,BLl层不应该有向用户显示错误的责任。它应该把错误传递给调用者,在这种情况下,UI层和调用者可以决定做什么。

如果您在上述示例中采纳了该建议,则应该删除MessageBox.Show,并可能由日志记录和/或错误收集代替。

改变你的catch:

catch (SqlException ex)
{
   MessageBox.Show(ex.ToString());
}

:

catch (Exception ex)
{
   MessageBox.Show(ex.ToString());
}

这样可以捕获try块中的任何错误,而不仅仅是"SqlException"类型的错误。您当前的错误可能不是"SqlException"

您的错误可能是因为UI无法从代码中访问。

让数据层生成UI组件违反了n层的设计原则。在n层中,您希望在设计的早期就决定在哪个层处理异常以及如何传输消息,因为修改可能很困难。

常见的方案:

  • 所有异常都被冒泡到UI层,在那里它们被适当地处理。数据层或业务层中唯一捕获的是可以在该层中正确处理的错误,或者捕获、记录和重新抛出。
  • 具有自定义返回类型,允许从业务层返回消息。这可以是来自所有BL方法的成功布尔返回值和某种类型的全局错误存储库("发生了一个或多个错误,这里是错误日志"类型的消息传递),也可以是包含异常的结果类型或复杂结果对象,可能还包括有关事务状态的其他信息等。

像"catch (SqlException ex)"那样捕获特定的异常是很好的做法,但为了调试,请尝试将"catch (SqlException ex)"替换为下面的语句。

catch (Exception exception)
{
    System.Diagnostics.Debug.WriteLine(exception.Message);
    throw;
}

在客户端和业务层都这样做,然后放置一个断点,调试,看看会发生什么。

我的猜测是在第一个catch语句中发生了一些事情,产生了另一种类型的异常,而这种异常没有在客户机上捕获。