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

如何在C#中的消息框中显示三层应用程序中SQL异常(唯一标识符)的错误消息?,c#,sql,sql-server,winforms,3-tier,C#,Sql,Sql Server,Winforms,3 Tier,我正在使用C#和SQL设计一个windows窗体3层应用程序。我设计了用户注册页面,该页面使用存储过程与数据库连接。我已经放置了文本框,以获取用户的输入。我对我的用户名列使用了唯一约束。由于我使用的是三层应用程序体系结构,所以我将register_用户函数放在了BLL中,并从UI中的按钮调用它。当我在文本框中输入repeateduser name时,它会抛出一个唯一约束的异常(如预期的那样),但我希望此消息应该显示在windows框中,并且我的应用程序不应该停止工作。我曾尝试在register_

我正在使用C#和SQL设计一个windows窗体3层应用程序。我设计了用户注册页面,该页面使用存储过程与数据库连接。我已经放置了文本框,以获取用户的输入。我对我的用户名列使用了唯一约束。由于我使用的是三层应用程序体系结构,所以我将register_用户函数放在了BLL中,并从UI中的按钮调用它。当我在文本框中输入repeateduser name时,它会抛出一个唯一约束的异常(如预期的那样),但我希望此消息应该显示在windows框中,并且我的应用程序不应该停止工作。我曾尝试在register_用户函数中使用try catch,但没有用。同样,我也尝试在UI中使用TryCatch(注册按钮),但再次失败。我在这里发布我的代码: 谢谢

//BLL

//用户界面

private void register\u按钮\u单击(对象发送方,事件参数e)
{
如果(第一个| | | | | | | | | | | | | | | | | | | | | |用户| | | | | | | | | | |密码(|文本=
{
alert1_label.Show();
error1_label.Show();
error1_label.Text=“您不能将必填字段留空”;
}

如果(password_text.text.Length像“catch(SqlException-ex)”一样捕获特定异常是一种很好的做法,但是为了调试,请尝试用下面的语句替换“catch(SqlException-ex)”

catch (Exception exception)
{
    System.Diagnostics.Debug.WriteLine(exception.Message);
    throw;
}
在客户端和业务层上都这样做,然后放置一个断点,调试并查看发生了什么


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

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

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

请记住,变量在C#中具有blockscope

超出此答案的范围,您必须重新考虑捕获异常的原因和时间。通常,只有知道如何处理异常时,您才能捕获异常。在当前的代码示例中,BLL和UI层都处理异常。如果操作正确,BLL层不应负责向用户显示错误。它应该-向调用者关闭错误,在这种情况下,UI层和调用者可以决定做什么

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

更改捕获:

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


通过这种方式,它可以捕获try块中的任何错误,而不仅仅是“SqlException”类型的错误。您当前的错误可能不是“SqlException”类型的错误。您的错误可能是因为无法从代码中的该点访问UI

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

共同计划:

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

它是否因错误而失败,还是刚刚开始工作?它因异常错误而失败,但我希望此错误显示在消息框中。异常发生在哪一行?在DAL Execute Query()中函数为了调试,如果不捕获任何异常,它将更加容易。另一种可能是在第一次机会时就中断。例外:哦!!我怎么会如此愚蠢……)感谢您的及时回复:)同样的问题让我很困惑,我使用第二个方案作为我的第一个选择,但我不知道失败时应该返回什么。但现在问题解决了:)如果可以肯定,为什么错误没有显示在消息框中?您应该试试,至少我已经按照您的建议工作了,但我失败了。什么我观察到,当我使用断点跟踪它时,它首先抛出一个异常,然后当我强制它继续时,它会在消息框中显示该异常。现在我只需从“调试”菜单中取消选中“异常”窗口中的“抛出”框。通过这种方法,我直接在消息框中看到异常。
catch (Exception exception)
{
    System.Diagnostics.Debug.WriteLine(exception.Message);
    throw;
}
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");
        }
    }   
   } 
catch (SqlException ex)
{
   MessageBox.Show(ex.ToString());
}
catch (Exception ex)
{
   MessageBox.Show(ex.ToString());
}