Как я могу показать сообщение об ошибке в окне сообщения в C # исключения SQL (уникальный идентификатор) в 3-уровневом приложении?

1

Я разрабатываю трехмерное приложение для Windows, используя С# и SQL. Я создал страницу регистрации пользователя, которая связана с базой данных с помощью хранимых процедур. Я поместил текстовые поля для ввода данных от пользователя. Я использовал уникальное ограничение для столбца имени пользователя. Поскольку я использую трехуровневую архитектуру приложения, поэтому я поместил функцию register_user в BLL и вызвал ее с помощью кнопки в пользовательском интерфейсе. Когда я вводил повторное имя пользователя в текстовое поле, оно генерирует исключение (как и ожидалось) уникального ограничения, но я хочу, чтобы это сообщение отображалось в окне окна, и мое приложение не должно перестать работать. Я попытался использовать try catch в функции register_user, но это бесполезно. Аналогично, я также попытался использовать 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);
            }
        }
    }
Теги:
sql-server
winforms
3-tier

4 ответа

1
Лучший ответ

Одной из проблем в вашем BLL является закрытие соединения, которое не открыто. В вашем методе register_user вас есть блок finally, который создает new DAL() объект new DAL() а затем вы вызываете CloseConnection.

Не видя этой реализации, я подозреваю, что вы хотели закрыть объект DAL, который вы создали в блоке try. Если это так, одно из возможных исправлений заключается в том, чтобы поднять переменную obj за пределы блока try, чтобы она стала доступна в блоке try и finally.

Помните, что переменные имеют blockscope в С#.

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-слой не должен нести ответственность за ошибки пользователя. Он должен передавать ошибки вызывающему абоненту, в этом случае слой пользовательского интерфейса и этот вызывающий абонент может решить, что делать.

Если вы примете этот совет в приведенном выше примере, MessageBox.Show должен быть удален и, возможно, заменен протоколированием и/или сборкой ошибок.

  • 0
    Ой!! Как я мог быть таким глупым .. :) Спасибо за ваш своевременный ответ :)
0

Хорошая практика - поймать определенные исключения, как вы, "catch (SqlException ex)", но для отладки попробуйте заменить "catch (SqlException ex)" на что-то вроде инструкции ниже.

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

Сделайте это как на клиентском, так и на бизнес-уровне, затем разместите точку останова, отлаживайте и посмотрите, что произойдет.

Я предполагаю, что что-то происходит в первом операторе catch, который генерирует другой тип исключения, который не попадает на клиента.

  • 0
    Ради отладки было бы еще проще, если бы не было исключений. Еще одна возможность - использовать исключение при первой же возможности: stackoverflow.com/questions/8218249/…
0

Вероятно, ваша ошибка возникает, потому что пользовательский интерфейс недоступен из этой точки в коде.

Это нарушает принципы проектирования n-уровня, чтобы ваш слой данных генерировал компоненты пользовательского интерфейса. В n-уровне вы хотите решить на раннем этапе проектирования, в каких случаях обрабатываются исключения и как передаются сообщения, поскольку переоснащение может быть затруднено.

Общие схемы:

  • Все исключения пузырятся до уровня пользовательского интерфейса, где они обрабатываются соответствующим образом. Единственные уловы в данных или бизнес-слое будут для ошибок, которые могут быть корректно обработаны внутри уровня, или для ловушки, регистрации и повторного броска.
  • Имейте пользовательские типы возвращаемых данных, которые позволяют отправлять сообщения из бизнес-слоев. Это может быть успешным логическим возвратом из всех методов BL и каким-то глобальным репозиторием ошибок ("произошла одна или несколько ошибок, вот сообщение об ошибках типа журнала ошибок") или что-то вроде типа результата или сложного объекта результата с включенным исключением и возможно, другая информация о состоянии транзакции и т.д.
  • 0
    Та же самая проблема меня сильно смутила, я использовал 2-ю схему в качестве своего самого первого варианта, но я был смущен тем, что возвращать при неудаче. но теперь это решено :)
0

Измените свой улов:

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

чтобы:

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

Таким образом, он обнаруживает ошибки внутри try-block, а не только ошибки SqlException -type. Ваша текущая ошибка может быть чем-то иным, чем "SqlException".

  • 0
    нет, это действительно исключение Sql наверняка.
  • 0
    Если это точно, почему ошибка не отображается в MessageBox? Вы должны попробовать это, по крайней мере
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню