第四章:通用类DBHelper和异常处理

本章目标

  1. 掌握异常处理try-catch-finally
  2. 会编写通用类DBHelper

本章内容

为什么要使用异常处理?

  1. 如下图所示:当在程序运行过程中出现以下几种情况:

    1. 无法打开数据库
    2. 数据操作出错
    3. 出现一些意外错误
    4. ………..

    出现异常,导致结果:程序异常终止,如何在异常中让程序恢复运行呢?所以要使用到异常处理机制。

1714272503362

什么是异常处理

  1. 什么是异常?

    程序在运行时发生的错误,叫异常。

  2. 什么是异常处理?

    在编写代码时,预知可能发生的异常,在程序中编码处理。

  3. 在 C# 语言中异常与异常处理语句包括三种形式,即 try catch、try finally、try catch finally。

    在上述三种异常处理的形式中所用到关键字其含义如下:

    try:用于检查发生的异常,并帮助发送任何可能的异常。 

    catch:以控制权更大的方式处理错误,可以有多个 catch 子句。 

    finally:无论是否引发了异常,finally 的代码块都将被执行。

如何处理异常

  1. 使用 try-catch 块捕获和处理异常

    在 try 语句中放置可能出现异常的语句,而在 catch 语句中放置异常时处理异常的语句,通常在 catch 语句中输出异常信息或者发送邮件给开发人员等。

    1. 语法:

      1
      2
      3
      4
      5
      6
      7
      8
      try
      {
      //程序代码,包含可能出现异常的代码
      }
      catch(处理的异常类型)
      {
      // 错误处理代码
      }
    2. 案例:在控制台输入年龄

      1. 未使用异常处理:

        1
        2
        3
        4
        5
        6
        7
        static void Main(string[] args)
        {
        Console.WriteLine("请输入年龄:");
        int age=int.Parse(Console.ReadLine());//将输入的字符串转换成数字

        Console.WriteLine("你的年龄是:{0}",age);
        }

        当在控制台输入错误时,出现结果如下:

        1714274844132

      2. 使用异常处理:

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        static void Main(string[] args)
        {
        try
        {
        Console.WriteLine("请输入年龄:");
        int age = int.Parse(Console.ReadLine());//将输入的字符串转换成数字

        Console.WriteLine("你的年龄是:{0}", age);
        }
        catch (Exception e)
        {
        Console.WriteLine("你输入的年龄有错!");
        }
        }

        当在控制台输入错误时,出现如下:

        1714275655733

      3. 异常类:Exception及常用的异常类

        序号 异常类 描述
        1 MemberAccessException 访问错误:类型成员不能被访问
        2 ArgumentException 参数错误:方法的参数无效
        3 ArgumentNullException 参数为空:给方法传递一个不可接受的空参数
        4 ArithmeticException 数学计算错误:由于数学运算导致的异常,覆盖面广。
        5 ArrayTypeMismatchException 数组类型不匹配
        6 DivideByZeroException 被零除
        7 FormatException 参数的格式不正确
        8 IndexOutOfRangeException 索引超出范围,小于0或比最后一个元素的索引还大
        9 InvalidCastException 非法强制转换,在显式转换失败时引发
        10 MulticastNotSupportedException 不支持的组播:组合两个非空委派失败时引发
        11 NotSupportedException 调用的方法在类中没有实现
        12 NullReferenceException 引用空引用对象时引发
        13 OutOfMemoryException 无法为新语句分配内存时引发,内存不足
        14 OverflowException 溢出
        15 StackOverflowException 栈溢出
        16 TypeInitializationException 错误的初始化类型:静态构造函数有问题时引发
        17 NotFiniteNumberException 无限大的值:数字不合法
      4. 多个catch捕获多个异常

        1. 为什么要使用多个catch捕获异常?

          虽然可以使用不带参数的 catch 子句捕捉任何类型的异常,但不推荐这种用法。 通常,您应该只捕捉那些您知道如何从中恢复的异常。

        2. 作用:

          通过使用多个 catch 块,可以捕获和处理多种类型的异常

        3. 语法:

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          try
          {
          //程序代码,包含可能出现异常的代码
          }
          catch(处理的异常类型)
          {
          // 错误处理代码
          }
          catch(处理的异常类型){
          // 错误处理代码
          }
          catch(处理的异常类型){
          // 错误处理代码
          }
        4. 注意事项:

          1. catch出现的顺序很重要,必须先出现异常的子类异常,再出现父类异常
        5. 案例:

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          try
          {
          Console.WriteLine("请输入第一个数:");
          int num1 = int.Parse(Console.ReadLine());
          Console.WriteLine("请输入第二个数:");
          int num2 = int.Parse(Console.ReadLine());

          int result = num1 / num2;

          Console.WriteLine("{0}/{1}={2}", num1, num2, result);
          }
          catch (FormatException ex)
          {
          Console.WriteLine(ex.Message);
          }
          catch (DivideByZeroException ex)
          {
          Console.WriteLine(ex.Message);
          }
          catch (Exception e)
          {
          Console.WriteLine(e.Message);
          }

          异常一:输入格式错误的情况

          1714354998258

          异常二:除数为0的情况

          1714355209303

  2. finally 块

    1. 作用:无论是否发生异常,都会执行

    2. 语法:

      1. 语法一:try-catch-finally

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        try
        {
        // ……
        }
        catch(处理的异常类型)
        {

        }
        finally
        {
        //.....无论什么情况都要执行的代码
        }
      2. 语法二:try-finally

        1
        2
        3
        4
        5
        6
        7
        8
        try
        {
        // ……
        }
        finally
        {
        //.....无论什么情况都要执行的代码
        }
    3. 案例:实现数据库操作登录功能

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      static void Main(string[] args)
      {
      Console.WriteLine("请输入用户名:");
      string userName = Console.ReadLine();
      Console.WriteLine("请输入密码:");
      string password = Console.ReadLine();

      string connString = "server=.;database=MySchool;uid=sa;pwd=sa;";
      SqlConnection conn = new SqlConnection(connString);

      try
      {
      conn.Open();//打开数据库
      string sql = "select count(1) from Admin where LoginId=@loginId and LoginPwd=@loginPwd;";
      SqlCommand cmd = new SqlCommand(sql, conn);
      cmd.Parameters.AddWithValue("@loginId", userName);
      cmd.Parameters.AddWithValue("@loginPwd", password);

      int count = (int)cmd.ExecuteScalar();
      if (count > 0)
      {
      Console.WriteLine("登录成功");
      }
      else
      {
      Console.WriteLine("登录失败");
      }
      }
      catch (Exception ex)
      {
      Console.WriteLine(ex.Message);
      }
      finally
      {
      conn.Close();//关闭连接
      }

      Console.ReadKey();
      }

通用类DBHelper

  1. 在项目配置文件中App.config,添加连接字符串节点:

    先在App.config里文件里添加这一行是连接字符串配置,用于指定连接到数据库所需的参数

    1
    2
    3
    <connectionStrings>
    <add name="名称" connectionString="server=.;database=MySchool;uid=sa;pwd=sa;"/>
    </connectionStrings>

    具体说明:

    :这是一个 XML 元素,用于包含所有连接字符串的集合。
    :这是 中的一个子元素,用于添加一个连接字符串。
    name=”Asset”:这是连接字符串的名称,可以在代码中使用该名称来引用该连接字符串。
    connectionString=”…”:这是连接字符串的实际值,包含了连接到数据库所需的各种参数。

  2. 右键添加引用Configuration

    1714360746133

  3. 创建DBHelper类

    1. 读取连接字符串,从配置文件App.config中读取

      1
      2
      3
      using System.Configuration;//引入命名空间

      public static readonly string connString = ConfigurationManager.ConnectionStrings["myschool"].ToString();
    2. 实现增、删、改操作的方法

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      /// <summary>
      /// 实现增,删,改操作
      /// </summary>
      /// <param name="commandText">sql语句</param>
      /// <param name="commandType">操作类型</param>
      /// <param name="parameters">参数</param>
      /// <returns></returns>
      public int ExecuteNonQuery(string commandText, CommandType commandType, params SqlParameter[] parameters)
      {
      using (SqlConnection connection = new SqlConnection(connString))
      {
      SqlCommand command = new SqlCommand(commandText, connection);
      command.CommandType = commandType;

      if (parameters != null)
      {
      command.Parameters.AddRange(parameters);//添加参数
      }

      connection.Open();
      return command.ExecuteNonQuery();
      }
      }
    3. 实现返回单行单列的操作

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      public object ExecuteScalar(string commandText, CommandType commandType, params SqlParameter[] parameters)
      {
      using (SqlConnection connection = new SqlConnection(connString))
      {
      SqlCommand command = new SqlCommand(commandText, connection);
      command.CommandType = commandType;

      if (parameters != null)
      {
      command.Parameters.AddRange(parameters);
      }

      connection.Open();
      return command.ExecuteScalar();
      }
      }
    4. 实现查询SqlDataReader操作

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      public SqlDataReader ExecuteReader(string commandText, CommandType commandType, params SqlParameter[] parameters)
      {
      SqlConnection connection = new SqlConnection(connString);//不能关闭连接


      SqlCommand command = new SqlCommand(commandText, connection);
      command.CommandType = commandType;

      if (parameters != null)
      {
      command.Parameters.AddRange(parameters);
      }

      connection.Open();
      return command.ExecuteReader(CommandBehavior.CloseConnection);//关闭DataReader对象后自动关闭连接

      }
    5. 返回DataTable操作

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      public DataTable ExecuteDataTable(string commandText, CommandType commandType, params SqlParameter[] parameters)
      {
      using (SqlConnection connection = new SqlConnection(connString))
      {
      SqlCommand command = new SqlCommand(commandText, connection);
      command.CommandType = commandType;

      if (parameters != null)
      {
      command.Parameters.AddRange(parameters);
      }

      SqlDataAdapter adapter = new SqlDataAdapter(command);
      DataTable dataTable = new DataTable();
      connection.Open();
      adapter.Fill(dataTable);
      return dataTable;
      }
      }
    6. 功能实现,调用DBHelpler类:

      1. 实现登录功能

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        public static void Login()
        {
        Console.WriteLine("请输入账号:");
        string loginId = Console.ReadLine();
        Console.WriteLine("请输入密码:");
        string loginPwd = Console.ReadLine();

        string sql = "select count(1) from Admin where LoginId=@loginId and LoginPwd=@loginPwd";
        DBHelper dBHelper2 = new DBHelper();

        //添加参数
        SqlParameter[] sp = new SqlParameter[]
        {
        new SqlParameter("@loginId",loginId),
        new SqlParameter("@loginPwd",loginPwd)
        };

        int count = Convert.ToInt32(dBHelper2.ExecuteScalar(sql, CommandType.Text, sp));
        if (count > 0)
        {
        Console.WriteLine("登录成功~");
        }
        else
        {
        Console.WriteLine("登录失败~");
        }

        }
      2. 实现新增功能(修改,删除类似则省略代码):

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        public static void AddUser()
        {
        Console.WriteLine("请输入账号:");
        string loginId = Console.ReadLine();
        Console.WriteLine("请输入密码:");
        string loginPwd = Console.ReadLine();

        string sql = "insert into Admin(LoginId,LoginPwd) values(@loginId,@loginPwd)";
        //添加参数
        SqlParameter[] sp = new SqlParameter[]
        {
        new SqlParameter("@loginId",loginId),
        new SqlParameter("@loginPwd",loginPwd)
        };
        DBHelper dBHelper = new DBHelper();
        int count = dBHelper.ExecuteNonQuery(sql, CommandType.Text, sp);
        if (count > 0)
        {
        Console.WriteLine("添加成功!");
        }
        else
        {
        Console.WriteLine("添加失败!");
        }
        }
      3. 实现查询全部信息,使用DataReader方式:

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        public static void SelectAll()
        {
        string sql = "select loginId,loginPwd from Admin";

        DBHelper dBHelper=new DBHelper();
        //无参数则传入null
        SqlDataReader sdr= dBHelper.ExecuteReader(sql, CommandType.Text, null);
        Console.WriteLine("账号\t密码");
        while (sdr.Read())
        {
        Console.WriteLine("{0}\t{1}", sdr["loginId"], sdr["loginPwd"]);
        }
        sdr.Close();//记得必须关闭
        }
      4. 实现查询全部信息,使用DataTable方式:

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        public static void SelectAll2()
        {
        string sql = "select loginId,loginPwd from Admin";

        DBHelper dBHelper = new DBHelper();
        //无参数则传入null
        DataTable dt = dBHelper.ExecuteDataTable(sql, CommandType.Text, null);
        Console.WriteLine("账号\t密码");

        foreach (DataRow dr in dt.Rows)
        {
        Console.WriteLine("{0}\t{1}", dr["loginId"], dr["loginPwd"]);
        }
        }