学习笔记:ADO.NET详解

了解ADO.NET

什么是ADO.NET呢?其实ADO.NET就是C#应用程序访问数据库的一个中间组件。
在这里插入图片描述
那ADO.NET又是由哪些部分组成呢?来看下面这张图
在这里插入图片描述
根据上面的图,来捋一遍数据库CRUD的流程:
连接数据库 >>> SqlCommand对数据库进行操作 >>>
查询出的数据放到DataSet中(若是增删改只是返回受影响记录条数,即返回int) >>> 关闭数据库

ADO.NET操作实例

准备工作:准备一张表,4个字段,10条测试记录;准备一个winForm,如图所示

在这里插入图片描述
接下来我们开始写代码,先写个查询

private void btn_query_Click(object sender, EventArgs e)
{
    using(SqlConnection conn = new SqlConnection("Data Source=DESKTOP-2HL1HGR\\SQL2014;Initial Catalog=TestDemo;Integrated Security=True"))
    {
    	//打开数据库连接
        conn.Open();
        //查询的sql语句
        string sql = "SELECT * FROM Student";
        //创建命令对象
        SqlCommand cmd = new SqlCommand(sql, conn);
        //执行查询返回的结果集
        SqlDataReader sdr = cmd.ExecuteReader();
        //每次查询前先清空textbox中原来的数据
        textBox1.Text = "";
        //显示标题
        textBox1.Text += "序号\t姓名\t年龄\t爱好\r\n\r\n";
        //如果结果集存在数据,则读取一行,不存在则sdr.Read()返回false
        while (sdr.Read())
        {
            textBox1.Text += sdr["F_id"].ToString() + "\t" + sdr["F_name"].ToString() + "\t" + sdr["F_age"].ToString() + "\t" + sdr["F_hobby"].ToString() + "\r\n";
        }
    }
}

结果如下
在这里插入图片描述
增加数据,由于此次只针对ADO.NET进行研究,所以为图方便我把增加的数据写死了。

private void btn_insert_Click(object sender, EventArgs e)
{
    using(SqlConnection conn = new SqlConnection("Data Source=DESKTOP-2HL1HGR\\SQL2014;Initial Catalog=TestDemo;Integrated Security=True"))
    {
        conn.Open();
        string sql = "INSERT INTO Student (F_name, F_age, F_hobby) VALUES ('小红', 20, '跳绳')";
        SqlCommand cmd = new SqlCommand(sql, conn);
        //返回受影响的行数
        int rows = cmd.ExecuteNonQuery();
        //如果受影响行数大于0,证明sql执行成功
        if (rows > 0)
            MessageBox.Show("新增成功!");
        else
            MessageBox.Show("新增失败!");
    }
}

执行结果:
在这里插入图片描述
修改数据

private void btn_edit_Click(object sender, EventArgs e)
{
    using(SqlConnection conn = new SqlConnection("Data Source=DESKTOP-2HL1HGR\\SQL2014;Initial Catalog=TestDemo;Integrated Security=True"))
    {
        conn.Open();
        string sql = "UPDATE Student SET F_name = '小强' WHERE F_Id = 4";
        SqlCommand cmd = new SqlCommand(sql, conn);
        int rows = cmd.ExecuteNonQuery();
        if (rows > 0)
            MessageBox.Show("修改成功!");
        else
            MessageBox.Show("修改失败!");
    }
}

执行结果
在这里插入图片描述
删除数据

private void btn_delete_Click(object sender, EventArgs e)
{
    using(SqlConnection conn = new SqlConnection("Data Source=DESKTOP-2HL1HGR\\SQL2014;Initial Catalog=TestDemo;Integrated Security=True"))
    {
        conn.Open();
        string sql = "DELETE FROM Student WHERE F_Id = 4";
        SqlCommand cmd = new SqlCommand(sql, conn);
        int rows = cmd.ExecuteNonQuery();
        if (rows > 0)
            MessageBox.Show("删除成功!");
        else
            MessageBox.Show("删除失败!");
    }
}

执行结果
在这里插入图片描述
ExecuteNonQuery()
返回受影响的行数,写法:

int rows = cmd.ExecuteNonQuery();

细心的同学可能发现了,增删改这3个方法执行起来一样的操作,无非是sql语句的变化而已,而在SqlCommand中基本就是用ExecuteNonQuery()方法,返回的是受影响的行数。
那么在增删改查这4个操作中最复杂的就是查询了。因为查询可能会返回一张表,一条记录,多条记录,单个值等等,所以
在SqlCommand中对于查询有多个方法可以使用,下面我就来讲解一下2种查询命令。

ExecuteReader()
返回的是一个结果集
这就是上面第一个查询用到的方法,通过游标把结果集的数据依次读出,写法:

 SqlDataReader sdr = cmd.ExecuteReader();
 while(sdr.Read()){
 		//读出的数据,格式例:sdr[0] 或 sdr["F_name"] 
 }

代码在上面已经写过,就不再重复写了。

ExecuteScalar()
返回第一行第一列的值
一般用于计数,写法:

Object count = cmd.ExecuteScalar();

观察以下代码,功能为从数据库取出记录数显示

private void btn_count_Click(object sender, EventArgs e)
{
    using(SqlConnection conn = new SqlConnection("Data Source=DESKTOP-2HL1HGR\\SQL2014;Initial Catalog=TestDemo;Integrated Security=True"))
    {
        conn.Open();
        string sql = "SELECT COUNT(*) FROM Student";
        SqlCommand cmd = new SqlCommand(sql, conn);
        Object count = cmd.ExecuteScalar();
        textBox1.Text = "记录数" + count.ToString();
    }
}

执行结果
在这里插入图片描述

思考:上述代码的缺陷

虽然以上的代码可以非常嗨皮地解决所有与数据库交互的问题,但是我们发现代码的冗余非常的大。
首先我们一直在写一句话using(SqlConnection…),其次我们也一直在打开数据库,还一直在实例化SqlCommand对象,其实这些代码都是重复的,我们不想去在重复的代码上浪费太多时间,所以我们把这些重复代码都抽象出来,SqlHelper就出现了。

SqlHelper

于是乎,我们新建一个抽象类SqlHelper来满足我们的需求

public abstract class SqlHelper
{
    //连接字符串
    public static readonly string connString = "Data Source=DESKTOP-2HL1HGR\\SQL2014;Initial Catalog=TestDemo;Integrated Security=True";

    //执行增删改方法
    public static int ExecteNonQuery(string sql)
    {
        using (SqlConnection conn = new SqlConnection(connString))
        {
            conn.Open();
            SqlCommand cmd = new SqlCommand(sql, conn);
            int rows = cmd.ExecuteNonQuery();
            return rows;
        }
    }

    //返回一个DataSet的查询方法
    public static DataSet ExecuteDataSet(string sql)
    {
        using (SqlConnection conn = new SqlConnection(connString))
        {
            conn.Open();
            SqlCommand cmd = new SqlCommand(sql, conn);
            //表示用于填充 DataSet 和更新 SQL Server 数据库的一组数据命令和一个数据库连接
            SqlDataAdapter sda = new SqlDataAdapter();
            //表示数据在内存中的缓存
            DataSet ds = new DataSet();
            sda.SelectCommand = cmd;
            sda.Fill(ds);
            return ds;
        }
    }
    
    //返回第一行第一列数据的查询方法
    public static Object ExecuteScalar(string sql)
    {
        using (SqlConnection conn = new SqlConnection(connString))
        {
            conn.Open();
            SqlCommand cmd = new SqlCommand(sql, conn);
            Object result = cmd.ExecuteScalar();
            return result;
        }
    }
}

此SqlHelper是我自己写的,目的只是为了给我前面写的方法做一个简单的抽象,而你们平常看到的SqlHelper可能会略有不同,只是根据不同的情况下判断了更多条件而已,理解SqlHelper的原理后可以自行扩充。

重写CRUD方法
我们写好了SqlHelper,那么现在开始重写我们的CRUD方法
首先重写增删改的方法

    // 新增一条记录
    private void btn_insert_Click(object sender, EventArgs e)
    {
        string sql = "INSERT INTO Student (F_name, F_age, F_hobby) VALUES ('小红', 20, '跳绳')";
        int rows = SqlHelper.ExecteNonQuery(sql);

        if (rows > 0)
            MessageBox.Show("新增成功!");
        else
            MessageBox.Show("新增失败!");
    }
    
    // 修改一条记录
    private void btn_edit_Click(object sender, EventArgs e)
    {
        string sql = "UPDATE Student SET F_name = '小强' WHERE F_Id = 4";
        int rows = SqlHelper.ExecteNonQuery(sql);

        if (rows > 0)
            MessageBox.Show("修改成功!");
        else
            MessageBox.Show("修改失败!");
    }

    // 删除一条记录
    private void btn_delete_Click(object sender, EventArgs e)
    {
        string sql = "DELETE FROM Student WHERE F_Id = 4";
        int rows = SqlHelper.ExecteNonQuery(sql);

        if (rows > 0)
            MessageBox.Show("删除成功!");
        else
            MessageBox.Show("删除失败!");
    }

感受到代码的简洁性了吗?真正需要用到的代码不过2行,就可以执行完增删改的操作了。

重写查询操作

private void btn_query_Click(object sender, EventArgs e)
{
    string sql = "SELECT * FROM Student";
    DataSet ds = SqlHelper.ExecuteDataSet(sql);
    //取到DataSet中的第一张表
    DataTable dt = ds.Tables[0];
    textBox1.Text = "";
    textBox1.Text += "序号\t姓名\t年龄\t爱好\r\n\r\n";
    //遍历DataTable中的所有行
    foreach (DataRow dr in dt.Rows)
    {
        textBox1.Text += dr["F_id"] + "\t" + dr["F_name"] + "\t" + dr["F_age"] + "\t" + dr["F_hobby"] + "\r\n";
    }
}

首先要捋清楚一个概念,DataSet是DataTable的集合,DataTable是DataRow的集合。
其中DataSet是表的集合,DataTable是一张表,DataRow是表中的一行数据。
一般来说,我们最多只需要取到数据库中的一张表就可以了。
所以上述代码的意思是,取到DataSet中的第一张表,再遍历表中所有行并且打印至TextBox1,是不是也没什么难度?

执行结果都一样,所以就不再贴图了。

ADO.NET与实体类的映射

一般来说,正规开发一定会用实体类来临时存储数据,我们在程序中可以把实体类作为参数传递,更加方便。
首先定义一个Student实体类

    public class Student
    {
        public int F_id { get; set; }
        public string F_name { get; set; }
        public int F_age { get; set; }
        public string F_hobby { get; set; }
    }

既然这写到这里我们不妨把数据改成动态的,不把他写死了。界面如图所示:
在这里插入图片描述
然后我们这么来改代码

/// <summary>
/// 查询Student表中的所有数据
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_query_Click(object sender, EventArgs e)
{
    string sql = "SELECT * FROM Student";
    DataSet ds = SqlHelper.ExecuteDataSet(sql);
    DataTable dt = ds.Tables[0];
    List<Student> list = new List<Student>();
    foreach (DataRow dr in dt.Rows)
    {
        Student stu = new Student();
        stu.F_id = Int32.Parse(dr["F_id"].ToString());
        stu.F_name = dr["F_name"].ToString();
        stu.F_age = Int32.Parse(dr["F_age"].ToString());
        stu.F_hobby = dr["F_hobby"].ToString();
        list.Add(stu);
    }
    textBox1.Text = "";
    textBox1.Text += "序号\t姓名\t年龄\t爱好\r\n\r\n";
    foreach(Student stu in list)
    {
        textBox1.Text += stu.F_id + "\t" + stu.F_name + "\t" + stu.F_age + "\t" + stu.F_hobby + "\r\n";
    }
}

/// <summary>
/// 新增一条记录
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_insert_Click(object sender, EventArgs e)
{
    Student stu = new Student();
    stu.F_name = tb_name.Text;
    stu.F_age = Int32.Parse(tb_age.Text);
    stu.F_hobby = tb_hobby.Text;

    string sql = string.Format("INSERT INTO Student (F_name, F_age, F_hobby) VALUES ('{0}', {1}, '{2}')", stu.F_name, stu.F_age, stu.F_hobby);
    int rows = SqlHelper.ExecteNonQuery(sql);

    if (rows > 0)
        MessageBox.Show("新增成功!");
    else
        MessageBox.Show("新增失败!");
}

/// <summary>
/// 修改一条记录
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_edit_Click(object sender, EventArgs e)
{
    Student stu = new Student();
    stu.F_id = Int32.Parse(tb_id.Text);
    stu.F_name = tb_name.Text;
    stu.F_age = Int32.Parse(tb_age.Text);
    stu.F_hobby = tb_hobby.Text;

    string sql = string.Format("UPDATE Student SET F_name = '{0}', F_age = {1}, F_hobby = '{2}' WHERE F_Id = {3}", stu.F_name, stu.F_age, stu.F_hobby, stu.F_id);
    int rows = SqlHelper.ExecteNonQuery(sql);

    if (rows > 0)
        MessageBox.Show("修改成功!");
    else
        MessageBox.Show("修改失败!");
}

/// <summary>
/// 删除一条记录
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_delete_Click(object sender, EventArgs e)
{
    Student stu = new Student();
    stu.F_id = Int32.Parse(tb_id.Text);

    string sql = "DELETE FROM Student WHERE F_Id = " + stu.F_id;
    int rows = SqlHelper.ExecteNonQuery(sql);

    if (rows > 0)
        MessageBox.Show("删除成功!");
    else
        MessageBox.Show("删除失败!");
}

如此便改完了我们的代码,此代码已测试可用,实现了ADO.NET与实体类的映射。

总结

实际上ADO.NET就只是一个与后台数据库交互的一种技术,本文从基础的写法到SqlHelper再到与实体的映射解释了ADO.NET的用法和使用途径,如有不足,欢迎指正。

猜你喜欢

转载自blog.csdn.net/weixin_42103026/article/details/88962745
今日推荐