C# 数据访问技术-

最近在学习用C#进行数据库相关操作,并在此进行了记录,参考的书本是C#从入门到精通,持续更改中......

1.用Connection对象连接数据库

1.1 连接对象

使用的数据库不同,引入不同的命名空间,然后通过命名空间中的Connection对象连接类连接数据库。主要包括以下几种访问数据库的对象类:SQL Server、MySQL、Odbc、OleDb、OracleClient,本文使用连接SQL Server,首先通过以下命令引用SQL Server数据提供程序

SQL Server

using System.Data.SqlClient;

1.2 数据库的连接、断开

调用SqlCommection对象的Open()方法打开数据库,通过SqlCommection对象的State属性判断数据库的连接状态。调用SqlCommection对象的Close()方法、Dispose()方法实现与数据库断开连接,并释放占用的资源。

新建一个项目

添加控件如下,”连接“按钮承担与数据库连接和断开的功能,代码如下:

//声明一个 连接数据库的字符串,        
string Constr;
//创建一个SqlConnection对象
SqlConnection sqlconn;
//创建一个bool 表示数据库连接状态
private bool connnstate = false;

/// <summary>
/// 数据库连接 断开
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_connect_Click(object sender, EventArgs e)
{
    try
    {
        if(connnstate==false)
        {//未连接
            if(tb_dbname.Text == "")
            {
                MessageBox.Show("数据库名称不能为空");
            }
            else
            {
                // string Constr = "server=服务器名称;database=数据库名称";uid=登录名;pwd=密码";
                Constr = "server=LAPTOP-DL9AITB5;database=" + tb_dbname.Text.Trim() + ";uid=sa;pwd=123456";
                sqlconn = new SqlConnection(Constr);
                sqlconn.Open();
                if (sqlconn.State == ConnectionState.Open)
                {   //处于连接状态时                            
                    connnstate = true;
                    tb_state.Text = "数据库已经连接!";
                    btn_connect.Text = "断开";                            
                }
            }
        }                
        else
        {   //已连接                 
            if (tb_dbname.Text == "")
            {
                MessageBox.Show("数据库名称不能为空");
            }
            else
            {
                Constr = "server=LAPTOP-DL9AITB5;database=" + tb_dbname.Text.Trim() + ";uid=sa;pwd=123456";

                sqlconn = new SqlConnection(Constr);
                sqlconn.Close();
                sqlconn.Dispose();
                if (sqlconn.State == ConnectionState.Closed)
                {   //处于连接状态时                            
                    connnstate = false;
                    tb_state.Text = "数据库已经断开!";
                    btn_connect.Text = "连接";
                }
            }

        }
    }
    catch (Exception ex)
    {
        MessageBox.Show("出现异常!\r" + ex.Message);
    }              
    
}

结果:

2.用Command对象执行SQL语句

Command对象是数据命令对象,功能:向数据库发送查询、更新、删除、添加操作的SQL语句。

2.1 设置数据源类型

Command对象最常用的三个属性,Connection、CommandText、CommandType。

Connection属性:设置SQL命令的使用对象:SqlConnection;

CommandText:设置对数据源执行的SQL语句或存储过程;

CommandType:指定CommandText的类型。

2.2 执行SQL

调用Command对象的ExecuteNonQuery()方法,执行发送的SQL语句;

调用Command对象的ExecuteReader()方法,执行SQL语句,获取数据表中指定字段所对应的数据;

调用Command对象的ExecuteScalar()方法,得到指定数据表的数据数量

3.ADO.NET中的数据容器

3.1 DataSet

DataSet是一个独立的数据库独立性对象,它包含一个或多个DataTable对象,以及这些表之间的关系。
它是一个内存中的对象,可以看作是一个小型数据库,具有独立的schema,可以在不同的应用程序之间传输数据。
DataSet支持XML数据交换,可以通过XmlSerializer序列化到XML,或者从XML反序列化回来。
DataSet支持事务,可以对多个表进行原子性操作。
DataSet提供了数据的完整性和一致性,可以通过约束和参照完整性来保证。

3.2 DataTable

DataTable是DataSet中的一个对象,可以看作是DataSet中的一个表。
它包含行和列,每行表示一条记录,每列表示一个字段。
DataTable可以与数据库表结构相对应,通常用于存储数据。
DataTable提供了数据的完整性和一致性,可以通过约束和参照完整性来保证。

3.3 DataReader:

DataReader是一个只读的数据容器,用于从数据库中读取数据。
它提供了一种高效的方式来读取大量数据,因为它是基于流的方式来读取数据的,一次读取一行。
DataReader不支持事务操作,因为它是一次性读取所有数据。
DataReader不支持XML数据交换,因为它是一次性读取所有数据。
DataAdapter:
DataAdapter是一个桥梁,用于在DataSet和数据库之间传输数据。
它可以填充DataSet,也可以更新数据库中的数据。
DataAdapter支持事务操作,可以对多个表进行原子性操作。
DataAdapter支持XML数据交换,可以通过XmlSerializer序列化到XML,或者从XML反序列化回来。

3.4 DataAdapter

DataAdapter是一个桥梁,用于在DataSet和数据库之间传输数据。
它可以填充DataSet,也可以更新数据库中的数据。
DataAdapter支持事务操作,可以对多个表进行原子性操作。
DataAdapter支持XML数据交换,可以通过XmlSerializer序列化到XML,或者从XML反序列化回来。

总结:

DataSet和DataTable都是用于存储数据的,DataSet是包含多个DataTable的容器,而DataTable是DataSet中的单个表。
DataReader用于高效读取大量数据,是一次性读取所有数据。
DataAdapter用于在DataSet和数据库之间传输数据,支持事务操作和XML数据交换。

4.数据库数据的查询、插入、删除和更新

DataAdapter对象通过相关属性向数据库发送SQL语句,实现查询、删除、插入、更新等功能,实现与数据源之间的互通。

SelectCommand属性:查询;

DeleteCommand属性:删除;

InsertCommand属性:插入;

UpdataCommand属性:更新。

4.1 检索数据源中的数据

调用DataAdapter对象的Fill()方法填充DataSet数据集,Fill方法使用SELECT语句检索数据。

窗体设计如下:

实现程序如下

 private void btn_jiazai_Click(object sender, EventArgs e)
 {
     if (connnstate==false)
     { 
         MessageBox.Show("数据库未连接!");               
     }
     else
     {
         try
         {
             jiazaiData();
         }
         catch(Exception ex) 
         {
         MessageBox.Show("加载失败!"+ex.Message);
         }                
     }
 }
private void jiazaiData()
{
  
    //创建一个SqlCommand对象
    // SqlCommand sqlcmd = new SqlCommand("select * from 表格名称",sqlconn);               
    sqlcmd = new SqlCommand("select * from " + tb_tbName.Text.Trim(), sqlconn);
    //创建一个SqlDataAdapter对象
    sda = new SqlDataAdapter();
    //将其SelectCommand属性设置为cmd
    sda.SelectCommand = sqlcmd;
    //创建了一个新的DataSet对象,这是一个内存中的数据库,可以容纳多个数据表
    ds = new DataSet();
    sda.Fill(ds, "cs");
    //将DataSet对象中的第一个数据表(索引为0)设置为dataGridView1控件的数据源
    dGV_1.DataSource = ds.Tables[0];
    //因为第一列为键值,所以将此改为已读
    dGV_1.Columns[0].ReadOnly = true;
   
}

其中,创建DateSet对象,可以理解为创建了一个虚拟数据库,用以保存所连接数据库中的将要处理数据表中的数据

结果

数据库表数据:

注意:表格名称不要出现错误,要保证数据库中存在!

上一方式是分了两个步骤(先连接数据库,再加载表格数据),如果用按钮直接连接数据库并打开指定鼠标表,代码如下

 //创建一个SqlConnection对象
 SqlConnection sqlconn;
 //创建一个SqlDataAdapter对象
 SqlDataAdapter sda;
 /// <summary>
/// 直接连接数据库并加载数据
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
 /// <summary>
 /// 直接连接数据库并加载数据
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void btn_jiazai2_Click(object sender, EventArgs e)
{
    try
    {
        Constr = "server=LAPTOP-DL9AITB5;database=" + tb_dbname.Text.Trim() + ";uid=sa;pwd=123456";
        sqlconn = new SqlConnection(Constr);
        sqlconn.Open();
        sqlcmd = new SqlCommand("select * from " + tb_tbname2.Text.Trim(), sqlconn);
        sda = new SqlDataAdapter();
        sda.SelectCommand = sqlcmd;
        ds = new DataSet();
        sda.Fill(ds, "cs");
        dGV_2.DataSource = ds.Tables[0];
        dGV_2.Columns[0].ReadOnly = true;
    }
    catch(Exception ex) 
    {
        MessageBox.Show("异常!" + ex);
    }
               
   
}

网上查看的代码一般都是打开数据库和关闭数据库一起出现,操作完之后即刻关闭,此做法本人还没有理解很到位, 但是为了确保在使用完数据库连接后,无论由于何种原因(比如异常)导致没有正常关闭连接,都能正确地关闭连接并释放资源,以维护系统的稳定性和资源的有效管理。添加了一个窗口关闭事件:

 private void Form1_FormClosing(object sender, FormClosingEventArgs e)
 {
     if(sqlconn.State==ConnectionState.Open)
     {
         sqlconn.Close();
         sqlconn.Dispose();
     }
     
 }

4.2  单条数据更新

使用DataAdapter对象的Update()方法,可以将DataSet中修改后的数据更新到数据库中。

注意:使用Update()方法,必须保证数据表中有主键,不然会出现异常。

此处实现的是修改单条数据

窗口设计

实现思路:加载数据表数据在DataGridView中显示,单击某条数据后,信息显示在对应的TextBox中(根据数据表表头,自己放置TextBox)。在响应TextBox中修改信息,然后单击修改按钮,通过Update方法更新数据源,删除操作同理;执行插入按钮时,填写各个TextBox,加入条件ID不能重复,然后通过Update方法更新数据源。

 1.需要添加一个DataGridView点击事件,使其显示单击的某条数据详细信息

设置DataGridView属性,不然会报错

ReadOnly=true;禁止编辑DataGridView

SelectionMode=FullRowSelect;使控件能够整行选择

private void dGV_1_CellClick(object sender, DataGridViewCellEventArgs e)
{
    textID.Text = dGV_1.SelectedCells[0].Value.ToString();
    textName.Text = dGV_1.SelectedCells[1].Value.ToString();
    textPass.Text = dGV_1.SelectedCells[2].Value.ToString();
}

效果

2.修改

private void btn_update_Click(object sender, EventArgs e)
{
   //单条数据修改
    if(connnstate==false)
    {
        MessageBox.Show("数据库未连接!");
    }
    else
    {
        
        // 从某个DataSet对象ds中获取一个名为"cs"的DataTable
        DataTable dt = ds.Tables["cs"];
        //调用SqlDataAdapter对象的FillSchema方法,填充DataTable的架构信息
        sda.FillSchema(dt, SchemaType.Mapped);
        //通过DataTable的Rows集合找到一个与txtNo控件中文本内容相匹配的DataRow。                
        DataRow dr = dt.Rows.Find(textID.Text);//主键
        //设置DataRow中的值 为textBox中的内容               
        dr["Name"] = this.textName.Text.Trim();
        dr["Pass"] = this.textPass.Text.Trim();
        //SqlCommandBuilder对象用于生成与SqlDataAdapter关联的更新命令,将DataSet中的变化反映到数据库中。               
        SqlCommandBuilder cmdbuider = new SqlCommandBuilder(sda);
        //更新数据源数据
        sda.Update(dt);
    }
}

将2 大二 222改为 大三 3333 结果

4.3 单条数据删除、插入

遇到的问题:操作前的数据依然在DataGridView中显示

解决:加载的数据前重新创建一个新的DataSet对象,这样每次加载的数据源都是新数据(前文加载加载数据按钮代码已更改)

(1)删除

 private void btn_delete_Click(object sender, EventArgs e)
 {
     //定义删除数据的SQL语句
     // string strsql = "delete from tb_PDic where ID=2";
     string strsql = "delete from " + tb_tbName.Text.Trim() + " where ID=" + textID.Text.Trim();
     try
     {
         if(connnstate != false)
         {
             //防止误操作,添加一个弹窗
             DialogResult dr = MessageBox.Show("确定删除?", "服务器信息", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);

             if (dr == DialogResult.Yes)
             {
                 SqlCommand sqlcmd = new SqlCommand(strsql, sqlconn);     //创建SqlCommand对象

                 //判断ExecuteNonQuery方法返回的参数是否大于0,大于0表示删除成功
                 if (Convert.ToInt32(sqlcmd.ExecuteNonQuery()) > 0)
                 {
                     MessageBox.Show("删除成功!");                            
                     jiazaiData(); 
                 }
                 else
                 {
                     MessageBox.Show("删除失败!不存在该条记录!!!");
                 }
             }
             else
             {
                 return;
             }
         }
         else
         {
             MessageBox.Show("数据库未连接");
         }
     }
     catch(Exception ex) 
     {
         MessageBox.Show("操作失败"+ex);
     }
     
 }

结果

(2)插入

窗口设计

private void btn_insert_Click(object sender, EventArgs e)
{
    string strsql2 = "INSERT INTO " + tb_tbName.Text.Trim() + " VALUES('" + addID.Text.Trim() + "','" + addName.Text.Trim() + "','" + addCode.Text.Trim() + "');";
    if (connnstate == true)
    {
        try
        {
            SqlCommand sqlcmd = new SqlCommand(strsql2, sqlconn);     //创建SqlCommand对象

            //判断ExecuteNonQuery方法返回的参数是否大于0,大于0表示操作成功
            if (Convert.ToInt32(sqlcmd.ExecuteNonQuery()) > 0)
            {
                //MessageBox.Show("插入成功!");
                jiazaiData();
                addID.Text = "";
                addName.Text = "";
                addCode.Text = "";
            }
            else
            {
                MessageBox.Show("失败!");
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show("失败!" + ex.Message);
        }


    }
    else
    {
        MessageBox.Show("数据库未连接");
    }
}

结果

4.4 批量更新数据

    直接在DataGridView控件中修改数据:用 DataTable的ImportRow()方法、将更改后的数据复制到一个DataTable中,再用DataAdapter对象的Update()方法更新到数据库中。

DataGridView属性设置:

单元格、列、行和控件ReadOnly属性都设置为false;

步骤:1.加载数据到DataGridView中显示,更改数据;2.选中某行已更改的数据,点击“更新”按钮,将该行的变化更新到数据库中(注意:更新到数据库的是选中单元格所在行的数据,无法一次性更新多行,更新不同行数据需要多次选中-更新)

  /// <summary>
  /// 批量修改事件
  /// </summary>
  /// <param name="sender"></param>
  /// <param name="e"></param>
  private void bt_piliangUpdate_Click(object sender, EventArgs e)
  {
      if(Update()==true)
      {
          MessageBox.Show("修改成功");
      }
  }
  /// <summary>
  /// 修改方法(bool) 更新完毕则为true 
  /// </summary>
  /// <param name="sender"></param>
  /// <param name="e"></param>
  SqlDataAdapter adapter;//声明一个SqlDataAdapter变量
  private new Boolean Update()
  {
      bool update = false;
      string strSql = "select * from tb_Login";
      DataTable dtUpdate = new DataTable();//用来存储所选表格更新后的数据
      dtUpdate = this.dbconn(strSql);
      DataTable dtShow = new DataTable();//用来存储数据源数据
      dtShow = (DataTable)this.dGV_2.DataSource;
      dtUpdate.ImportRow(dtShow.Rows[intindex]);//将dtShow中指定行的数据导入到dtUpdate中
      try
      {
          SqlCommandBuilder CommandBuiler;
          CommandBuiler = new SqlCommandBuilder(this.adapter);//创建一个新的SqlCommandBuilder对象,与sda关联。
          this.adapter.Update(dtUpdate);//使用Update方法将dtUpdate中的更改应用到数据库。
          dtUpdate.AcceptChanges();
          update = true;
      }
      catch (Exception ex) 
      {
          MessageBox.Show("未发现有变化\r" + ex);
      }
      return update;
      
  }
  /// <summary>
  /// DataTable类型的表格填充方法
  /// </summary>
  /// <param name="strSql"></param>
  /// <returns></returns>
  private DataTable dbconn(string strsql)
  {
      DataTable dtSelect = new DataTable();//创建一个新的DataTable对象来存储查询结果。
      if (sqlconn.State == ConnectionState.Open)
      {
          this.adapter = new SqlDataAdapter(strsql, sqlconn);//创建一个新的SqlDataAdapter对象,它用于执行SQL命令并填充DataTable                
          int rnt = this.adapter.Fill(dtSelect);//使用Fill方法将查询结果填充到dtSelect表中。                
      }
      else
      {
          MessageBox.Show("数据库未连接");
          
      }
      return dtSelect;//方法返回填充好的DataTable         
  }
  int intindex = 0;
  /// <summary>
  /// 点击任何单元格时触发
  /// </summary>
  /// <param name="sender"></param>
  /// <param name="e"></param>
  private void dGV_2_CellClick(object sender, DataGridViewCellEventArgs e)
  {
      // 获取被点击的行的索引
      intindex = e.RowIndex;
  }

过程演示

1.加载数据

2.在DataGridView中更改数据

3.按行更新

选中1---->更新

选中3----->更新

选中6----->更新

由数据库结果可见,2并没选中更新过,所以数据源中的数据未改变。

  • 12
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值