ADO.NET 封装 SqlHelper

开发工具:Visual Studio 2019

需要的包

System.Data.SqlClient

ADO.NET的类及主要成员

  1. Connection:用来连接数据库,常用方法Open()
    使用示例
string conString="连接字符串";
string sql="sql语句";
//不使用C# 8.0 的using新语法 
using(SqlConnection con = new SqlConnection(conString))
{
      using(SqlCommand cmd = new SqlCommand(sql,con))
      {
            //若使用无参构造
            //cmd.CommandText = sql;
            //cmd.Connection = con;

            //推荐:连接对象,最晚打开,最早关闭,节省资源
            //用前打开连接,用完立刻关闭连接
            con.Open();
            Console.WriteLine("打开连接成功");

            //省略数据库操作
      }
      Console.WriteLine("关闭连接,释放资源");
}
  1. Command:用来执行SQL语句,常用方法
  • ExecuteNonQuery():Insert、delete、update语句时使用
    返回int类型,表示执行SQL语句后,所影响的行数,只有执行Insert、delete、update语句时,才会返回所影响的行数,执行任何其它SQL语句永远返回-1

  • ExcuteScalar():当执行返回单个结果的时候(一行一列,如COUNT函数)时使用,执行聚合函数不返回null(COUNT最少返回0),执行的不是聚合函数,可能返回null,要判断

  • ExecuteReader():当查询出多行多列结果的时候使用

  1. DataReader:只读、只进的结果集,一条一条读取数据(StreamReader、XmlReader微软的类库中这些Reader的使用方式都差不多),不能修改,不能后退,常用方法Reader()和索引器
  2. DataAdapter:一个封装了上面三个对象的对象

封装SqlHelper

先写好App.config配置文件

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
    <add name="连接名" connectionString="连接字符串"/>
  </connectionStrings>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
    </startup>
</configuration>

对SqlCommand中的方法进行封装,函数名和返回值相同

public static class SqlHelper
{
    //定义一个连接字符串,从App.config文件读取
    //需要 System.Configuration.ConfigurationManager
    private static readonly string ConStr =
        ConfigurationManager.ConnectionStrings["连接名"].ConnectionString;

    /// <summary>
    /// 执行增删改操作
    /// </summary>
    /// <param name="sql">sql语句</param>
    /// <param name="pms">参数</param>
    /// <returns></returns>
    public static int ExcuteNonQuery(string sql, params SqlParameter[] pms)
    {
        using (SqlConnection con = new SqlConnection(ConStr))
        {
            using (SqlCommand cmd = new SqlCommand(sql, con))
            {
                //避免pms传入长度为0的数组
                if (pms != null)
                {
                    cmd.Parameters.AddRange(pms);
                }
                con.Open();
                return cmd.ExecuteNonQuery();
            }
        }
    }

    /// <summary>
    /// 执行查询,返回单个值的方法
    /// </summary>
    /// <param name="sql">SQL语句</param>
    /// <param name="pms">参数</param>
    /// <returns></returns>
    public static object ExecuteScalar(string sql, params SqlParameter[] pms)
    {
        using (SqlConnection con = new SqlConnection(ConStr))
        {
            using (SqlCommand cmd = new SqlCommand(sql, con))
            {
                if (pms != null)
                {
                    cmd.Parameters.AddRange(pms);
                }
                con.Open();
                return cmd.ExecuteScalar();
            }
        }
    }

    /// <summary>
    /// 执行查询,返回多行多列的方法
    /// </summary>
    /// <param name="sql">SQL语句</param>
    /// <param name="pms">参数</param>
    /// <returns></returns>
    public static SqlDataReader ExecuteReader(string sql, params SqlParameter[] pms)
    {
        SqlConnection con = new SqlConnection(ConStr);
        using (SqlCommand cmd = new SqlCommand(sql, con))
        {
            if (pms != null)
            {
                cmd.Parameters.AddRange(pms);
            }
            try
            {
                con.Open();
                return cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
            }
            catch
            {
                con.Close();
                con.Dispose();
                throw;
                //让外层知道出现异常,抛出全部异常
                //throw new Exception();可以写在任何地方,但只抛出自己写的一个异常
            }
            //返回之前连接对象就关闭了
            //使用reader时,连接必须是打开的
            //不使用using创建连接对象,会导致reader使用完毕仍不放入连接池
            //使用CommandBehavior.CloseConnection时,其它地方使用using调用完reader会关闭连接对象

            //System.Data.CommandBehavior.CloseConnection这个枚举参数,表示将来使用完毕SqlDataReader后
            //在关闭reader的同时,在SqlDataReader内部会将关联的Connection对象也将关闭掉

            //但是连接对象没有使用using,出异常将关闭不了连接,要使用try catch语句关闭连接
        }
    }

    /// <summary>
    /// 查询数据库返回DataTable
    /// </summary>
    /// <param name="sql">SQL语句</param>
    /// <param name="pms">参数</param>
    /// <returns></returns>
    public static DataTable ExecuteDataTable(string sql, params SqlParameter[] pms)
    {
        DataTable dt = new DataTable();
        using (SqlDataAdapter adapter = new SqlDataAdapter(sql, ConStr))
        {
            if (pms != null)
            {
                adapter.SelectCommand.Parameters.AddRange(pms);
            }
            adapter.Fill(dt);
        }

        return dt;
    }
}

封装SqlHelper,包含执行存储过程

上述代码执行存储过程时需要在sql语句中添加exec以及参数名,可以在方法中添加一个参数简化,也可以重载,使用存储过程时再调用相应的方法
最终完成代码

public static class SqlHelper
{
    //定义一个连接字符串,从App.config文件读取
    //需要 System.Configuration.ConfigurationManager
    private static readonly string ConStr =
        ConfigurationManager.ConnectionStrings["连接名"].ConnectionString;


    /// <summary>
    /// 执行增删改操作
    /// </summary>
    /// <param name="sql">sql语句</param>
    /// <param name="pms">参数</param>
    /// <returns></returns>
    public static int ExcuteNonQuery(string sql, CommandType cmdType, params SqlParameter[] pms)
    {
        using (SqlConnection con = new SqlConnection(ConStr))
        {
            using (SqlCommand cmd = new SqlCommand(sql, con))
            {
                cmd.CommandType = cmdType;
                if (pms != null)
                {
                    cmd.Parameters.AddRange(pms);
                }
                con.Open();
                return cmd.ExecuteNonQuery();
            }
        }
    }

    /// <summary>
    /// 执行查询,返回单个值的方法
    /// </summary>
    /// <param name="sql">SQL语句</param>
    /// <param name="pms">参数</param>
    /// <returns></returns>
    public static object ExecuteScalar(string sql, CommandType cmdType, params SqlParameter[] pms)
    {
        using (SqlConnection con = new SqlConnection(ConStr))
        {
            using (SqlCommand cmd = new SqlCommand(sql, con))
            {
                cmd.CommandType = cmdType;
                if (pms != null)
                {
                    cmd.Parameters.AddRange(pms);
                }
                con.Open();
                return cmd.ExecuteScalar();
            }
        }
    }

    /// <summary>
    /// 执行查询,返回多行多列的方法
    /// </summary>
    /// <param name="sql">SQL语句</param>
    /// <param name="pms">参数</param>
    /// <returns></returns>
    public static SqlDataReader ExecuteReader(string sql, CommandType cmdType, params SqlParameter[] pms)
    {
        SqlConnection con = new SqlConnection(ConStr);
        using (SqlCommand cmd = new SqlCommand(sql, con))
        {
            cmd.CommandType = cmdType;
            if (pms != null)
            {
                cmd.Parameters.AddRange(pms);
            }
            try
            {
                con.Open();
                return cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
            }
            catch
            {
                con.Close();
                con.Dispose();
                throw;
            }

        }
    }

    /// <summary>
    /// 查询数据库返回DataTable
    /// </summary>
    /// <param name="sql">SQL语句</param>
    /// <param name="pms">参数</param>
    /// <returns></returns>
    public static DataTable ExecuteDataTable(string sql, CommandType cmdType, params SqlParameter[] pms)
    {
        DataTable dt = new DataTable();
        using (SqlDataAdapter adapter = new SqlDataAdapter(sql, ConStr))
        {
            adapter.SelectCommand.CommandType = cmdType;
            if (pms != null)
            {
                adapter.SelectCommand.Parameters.AddRange(pms);
            }
            adapter.Fill(dt);
        }

        return dt;
    }
}

使用示例

static void Main(string[] args)
{
    string username = "admin";
    string password = "123456";
    string sql = "select COUNT(*) from Users where Username=@username and Password=@password";
    SqlParameter[] pms = new SqlParameter[]
    {
        new SqlParameter("@username",SqlDbType.NVarChar,10){Value=username},
        new SqlParameter("@password",SqlDbType.VarChar,32){Value=password}
    };
    int count = Convert.ToInt32(SqlHelper.ExecuteScalar(sql, pms));
    //int count = Convert.ToInt32(SqlHelper.ExecuteScalar(sql, CommandType.Text, pms));
    if (count > 0)
    {
        Console.WriteLine("登录成功");
    }
    else
    {
        Console.WriteLine("用户名或密码错误");
    }
}

执行存储过程的话

static void Main(string[] args)
{
    string username = "admin";
    string password = "123456";
    string sql = "存储过程名";
    SqlParameter[] pms = new SqlParameter[]
    {
        new SqlParameter("@username",SqlDbType.NVarChar,10){Value=username},
        new SqlParameter("@password",SqlDbType.VarChar,32){Value=password}
    };
    int count = Convert.ToInt32(SqlHelper.ExecuteScalar(sql, CommandType.StoredProcedure, pms));
    if (count > 0)
    {
        Console.WriteLine("登录成功");
    }
    else
    {
        Console.WriteLine("用户名或密码错误");
    }
}

注意事项(SqlDataReader)

使用SqlDataReader时必须保证连接是打开状态,当SqlDataReader使用完毕后,必须把SqlDataReader关闭,释放,同时关闭释放连接对象

static void Main(string[] args)
{
    string conStr = "";
    using (SqlConnection con = new SqlConnection(conStr))
    {
        string sql = "select * from Users";

        using (SqlCommand cmd = new SqlCommand(sql, con))
        {
            con.Open();
            using (SqlDataReader reader = cmd.ExecuteReader())
            {
                //查询语句在服务器端执行
                //执行完毕后,服务器端查询出数据,保存在服务器内存中,并没有返回给应用程序
                //只是返回给应用程序一个reader对象,这个对象就是用来获取数据的对象

                //通过reader一条一条获取数据
                //1、在获取数据之前,先判断本次执行查询后是否查询到数据
                if (reader.HasRows)//有数据则为true
                {
                    //2、如果有数据,那么接下来就一条一条获取数据
                    //reader一次只能取一条数据
                    //每次获取之前要先调用Read()方法
                    //bool Read()
                    //使 SqlDataReader 前进到下一条记录。移动到null上返回false
                    //如果存在多个行,则为 true;否则为 false。
                    //移动到下一条数据,上一条自动销毁
                    while (reader.Read())
                    {
                        //获取当前reader指向的数据
                        //FieldCount 获取查询到的当前行中的列数。 
                        for (int i = 0; i < reader.FieldCount; i++)
                        {
                            //GetValue只能通过列索引来获取列的值
                            //reader[]可以通过列名来获取列的值,如,reader["Id"]
                            //字符串索引器调用GetOrdinal方法,在给定列名称的情况下获取列序号。 
                            //Console.Write(reader.GetValue(i)+"\t");
                            Console.Write(reader[i] + "\t");
                            //遇到数据库中的null值输出空字符串,因为是DBNull.Value,不是C#的null,不报异常

                            //GetXXX使用强类型读取列中数据
                            //读取到的数据直接就是对应的类型,不是object类型,使用起来更方便
                            //reader只能读取数据,不能修改数据
                            //reader[i] = "";报错
                        }
                        Console.WriteLine();
                    }
                    //使用reader时必须保证连接是打开状态
                    //当reader使用完毕后,必须把reader关闭,释放,同时关闭释放连接对象
                }
                else
                {
                    Console.WriteLine("没有查询到任何数据");
                }
            }
        }
    }
}

使用GetXxxx()方法获取数据

static void Main(string[] args)
{
    string conStr = "";
    using (SqlConnection con = new SqlConnection(conStr))
    {
        string sql = "select * from Users";

        using (SqlCommand cmd = new SqlCommand(sql, con))
        {
            con.Open();
            using (SqlDataReader reader = cmd.ExecuteReader())
            {
                if (reader.HasRows)
                {
                    while (reader.Read())
                    {
                        Console.Write(reader.IsDBNull(0) ? "null" : reader.GetInt32(0) + "\t");
                        Console.Write(reader.IsDBNull(1) ? "null" : reader.GetString(1) + "\t");
                        Console.Write(reader.IsDBNull(2) ? "null" : reader.GetBoolean(2) + "\t");
                        Console.WriteLine();
                    }
                }
            }
        }
    }
}

ADO.NET 封装 SqlHelper 结束

不使用 C# 8.0 的 using 语法确实看着很乱

posted @ 2021-02-11 16:18  .NET好耶  阅读(402)  评论(0编辑  收藏  举报