ADO.NET操作SQL Server数据库的步骤:
所要用到的数据对象:
数据库连接对象:SqlConnection连接对象
SQL语句执行对象:SqlCommand对象
读取数据对象:DataReader对象
数据适配器对象:DataAdapter对象
数据集合:DataSet对象
第一步:连接数据库!
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace SQLConn
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//连接数据库的操作
private void button1_Click(object sender, EventArgs e)
{
//连接数据库的步骤:
if(textBox1.Text=="")
{
MessageBox.Show("请输入要链接的数据库的名称");
}
else
{
try
{
//1.声明一个字符串用于存储连接数据库字符串
string ConStr = "server=.;database="+textBox1.Text.Trim()+";uid=sa;pwd=*******";
//2.创建一个SqlConnection对象
SqlConnection conn = new SqlConnection(ConStr);
conn.Open(); //打开连接
if(conn.State==ConnectionState.Open) //判断当前的连接状态
{
//显示状态信息
label1.Text="数据库【"+textBox1.Text.Trim()+"】已经连接并且打开";
}
}
catch
{
MessageBox.Show("数据库连接失败");
}
}
}
//关闭数据库的操作步骤:
//通过SqlConnection对象关闭
//关闭连接有两种方法,一种是Close一种是Dispose
//Close关闭连接后,不清理连接所占用的资源,可以再调用Open方法打开连接,而且无错误
//Dispose方法关闭连接后,会清理连接所占用的资源,不可以直接通过Open方法打开连接,必须重新初始化连接再打开
SqlConnection conn;
private void button2_Click(object sender, EventArgs e)
{
if(textBox2.Text=="")
{
MessageBox.Show("请输入要连接的数据库");
}
else
{
try
{
string ConStr = "server=.;database=" + textBox2.Text.Trim() + ";uid=sa;pwd=********";
conn = new SqlConnection(ConStr);
conn.Open();
if(conn.State==ConnectionState.Open)
{
richTextBox1.Text = "数据库已经连接并且打开";
}
}
catch
{
MessageBox.Show("数据库连接失败");
}
}
}
//Close方法关闭连接并且重新打开连接
private void button3_Click(object sender, EventArgs e)
{
try
{
string str = "";
conn.Close();
if(conn.State==ConnectionState.Closed)
{
str = "数据库已经成功关闭\n";
}
conn.Open();
if(conn.State==ConnectionState.Open)
{
str += "数据库已经成功打开\n";
}
richTextBox1.Text = str;
}
catch(Exception ex)
{
richTextBox1.Text = ex.Message;
}
}
//Dispose方法关闭连接并且重新打开
private void button4_Click(object sender, EventArgs e)
{
try
{
conn.Dispose();
conn.Open();
//string ConStr = "server=.;database=" + textBox2.Text.Trim() + ";uid=sa;pwd=*********";
//conn = new SqlConnection(ConStr);
//conn.Open();
//MessageBox.Show("初始化后连接成功");
//注释: 先CTRL + K,然后CTRL + C
//取消注释: 先CTRL + K,然后CTRL + U
}
catch(Exception ex)
{
richTextBox1.Text = ex.Message;
}
}
//Command对象是一个数据命令对象,向数据库发送SQL语句
//Command对象有四种方式 SqlCommand,OleDbCommand,OdbcCommand,OracleCommand 引入程序集的方法是右键项目,添加引用
//Command有三个属性Connection 用于设置SqlCommand 的SqlConnection
// CommandText 用于设置要对数据源执行的Sql语句或者存储过程
// CommandType 用于设置指定CommandText的类型 CommandType的枚举类型 StoreProcedure:存储过程名字;TableDirect:表的名称;Text:SQL文本命令
private void button5_Click(object sender, EventArgs e)
{
try
{
if (conn.State == ConnectionState.Open)
{
//1.创建数据命令对象SqlCommand
SqlCommand cmd = new SqlCommand();
//2.设置Connection属性
cmd.Connection = conn;
//3.设置CommandText属性
cmd.CommandText = "select count(*)from tb_user";
//4.设置CommandType的属性 为Text,使其只执行SQL语句的文本形式
cmd.CommandType = CommandType.Text;
//5.执行SQL
int i = Convert.ToInt32(cmd.ExecuteScalar());
label4.Text = "数据表中有:" + i + "条数据";
///*执行SQL语句的几种方式*/
//方式一:执行SQL并且返回收影响的行数ExecuteNonQuery方法发送SQL
cmd.CommandText = "update tb_user set user_name='好好先生' where user_id=1";
int i2 = Convert.ToInt32(cmd.ExecuteNonQuery());
MessageBox.Show("i2=" + i2);
//方式二:ExcuteReader方法
//执行SQL,并且生成一个包含数据的SqlDataReader对象的实例
cmd.CommandText = "select * from tb_user";
SqlDataReader sdr = cmd.ExecuteReader();
while(sdr.Read()) //用while循环读取SqlDataReader
{
listView1.Items.Add(sdr[1].ToString());
}
conn.Dispose();
button5.Enabled = false;
//方式三:ExecuteScalar 返回结果集中的第一行的第一列 或者空引用
//常和聚合函数一起使用
//常见的聚合函数AVG COUNT(expr) COOUNT(*) MAX(expr)忽略空值 MIN(expr)忽略空值 SUM(expr)
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
第二步:执行SQL语句!
Command对象有三个重要的属性,分别是
Connection,设置数据库连接对象
CommandText,设置要执行的SQL语句或者存储过程(存储过程的名字)
CommandType,设置指定的CommandText的类型,有三个枚举成员:StoredProcedure存储过程名称
TableDirect:表的名称, Text:SQL文本命令
执行SQL语句有多种方法:
ExecuteNonQuery:执行SQL,并返回受影响的行数,在使用SqlCommand向数据库发送增删改命令时,通常使用此方法
public override int ExecuteNonQuery()
ExecuteReader:执行SQL,并生成一个包含数据的SqlDataReader对象的实例
public SqlDataReader ExecuteReader() 返回值:一个SqlDataReader对象
eg: 读取时:
SqlDataReader sdr=cmd.ExecuteReader();
while(sdr.Read())
{
listView1.Items.Add(sdr[1].ToString());
}
ExecuteScalar:执行SQL,返回结果集中的第一行第一列
public override Object ExecuteScalar() 返回值:结果集中第一行第一列或空引用
此方法通常和集合函数一起使用,获得数据表中的数据量
AVG(expr) 列平均值,该列只能包含数字数据
COUNT(expr),COUNT(*) 列值的计数(如果指定列名expr),表或分组中所有行的计数(如果指定*)
忽略空值,但是COUNT(*)在计数中包含空值
MAX(expr) 列中最大值(文本数据类型中按字母顺序排在最后的值),忽略空值
MIN(expr) 列中最小值(文本数据类型中按字母顺序排在最前的值),忽略空值
SUM(expr) 列值得合计,该列只能包含数据
第三部:读取数据!
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace SQLDataReader
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//DataReader是数据读取器对象,提供只读向前的游标
//同样的对于不同的数据库连接,有不同的DataReader类型
//SqlDataReader OleDbDataReader OdbcDataReader OracleDataReader
//在使用DataReader对象读取数据时,可以使用ExecuteReader方法,根据SQL语句的结果创建一个SqlDataReader对象.
/*在创建DataRelation时,它首先验证是否可以建立联系。在创建DataRelation和将其添加到DataRelationCollection(DataSet的DataRelation对象的集合)之间的这段时间,
可以对父行或者子行进行其他修改*/
private void button1_Click(object sender, EventArgs e)
{
SqlDataReader sdr=null;
try
{
SqlConnection conn = new SqlConnection("server=.;database=db_myr;uid=sa;pwd='**********'");
conn.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = "select * from tb_user";
cmd.CommandType = CommandType.Text;
sdr = cmd.ExecuteReader();
//读取数据
//判断查询结果中是否有值
//通过SqlDataReader对象的HasRows属性获取一个值,该值指示SqlDataReader是否包含一行或者多行,即判断查询结果中是否有值,返回值为bool
sdr.Read();
//Read方法的返回值,如果存在多个行则返回true
/*对于每个关联的SqlConnection,一次只能打开一个SqlDataReader,在第一个关闭之前,打开另一个的任何尝试都是失败的
过程是:ExecuteReader方法执行->根据SQL语句返回一个SqlDataReader->再调用Read方法读取数据(必须调用Read,因为SqlDataReader的默认位置是在第一条记录前面)*/
//使用完SqlDataReader对象后,用Close方法关掉
if(sdr.HasRows)
{
MessageBox.Show("数据表中有值");
sdr.Close();
}
else
{
MessageBox.Show("数据表中无值");
sdr.Close();
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
sdr.Close();
}
}
}
}
第四部:数据适配器对象
using System;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;
namespace SQLDataAdapter
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//第一部分:DataAdapter对象概述
//DataAdapter对象是一个数据适配器对象,是DataSet与数据源之间的桥梁。DataAdapter对象提供四个属性,用于实现与数据源之间的互通
/*
SelectCommand属性,向数据库发送查询sql语句
DeleteCommand属性,向数据库发送删除sql语句
InsertCommand属性,...
UpdateCommand属性,...
在对数据库进行操作时,只要将这四个属性设置成相应的SQL语句即可,DataAdapter对象中还有几个主要的方法:
方法一:Fill方法用数据填充DataSet
public int Fill(DataSet dataSet,string srcTable)
dataSet:用于记录和架构填充的DataSet
srcTable:用于表映射的原表名称
返回值:已在DataSet中成功添加或者刷新的行数,这不包括受不返回行的语句的影响的行
在创建DataAdapter的实例时,将其读/写属性设置为初值,MissingMappingAction属性设置为MissingMappingAction.Passthrough,
MissingMappingAcion属性设置为MissingSchemaAction.Add
方法二:Update方法更新数据库时,DataAdapter将调用DeleteCommand,InsertCommand,UpdateCommand属性
public int Update(DataTable dateTable)
dataTable:用于更新数据源的DataTable
返回值:DataSet中成功更新的行数
*/
/*第二部分:填充DataSet数据集*/
//通过DataAdapter对象的Fill方法填充DataSet数据集,Fill方法使用Select语句从数据源中检索数据,与Select命令相关联的Connection对象必须有效,但是不需要将其打开
//DataSet和DataTable对象从MarshalByCalueComponent(实现IComponent冰提供远程控制的组建的基实现)继承而来,并且支持用于运城处理ISerializable接口
SqlConnection conn;
DataSet ds;
SqlDataAdapter sda;
private void button1_Click(object sender, EventArgs e)
{
conn = new SqlConnection("server=.;database=db_myr;uid=sa;pwd=**********");
SqlCommand cmd = new SqlCommand("select * from tb_user", conn);
sda = new SqlDataAdapter();
sda.SelectCommand = cmd;//设置SqlDataAdapter对象的SelectCommand属性为cmd
//创建一个DataSet对象
ds = new DataSet();
//使用SqlDataAdapter对象的Fill方法填充DataSet数据集
sda.Fill(ds, "cs");
//设置dataGridView1控件的数据源
dataGridView1.DataSource = ds.Tables[0];
}
//第三部分:更新数据源
/*使用DataAdapter对象的Update方法,可以将DataSet中修改过的数据及时地更新到数据库中
在调用Update方法之前,要实例化一个CommandBuilder类,它能自动根据DataAdapter的SelectCommand的SQL语句判断其他InsertCommand,UpdateCommand,DeleteCommand
这样就不需要设置DataAdapter的InsertCommand,UpdateCommand,DeleteCommand
直接使用DataAdapter的Update方法来更新DataSet,DataTable,DataRow*/
//沿用上面的例子进行改造
private void button2_Click(object sender, EventArgs e)
{
DataTable dt = ds.Tables["cs"]; //创建一个DataTable
sda.FillSchema(dt, SchemaType.Mapped); //把表结构加载到tb_user中
DataRow dr = dt.Rows.Find(txtNo.Text); //创建一个DataRow
//设置DataRow中的值
dr["user_name"] = txtName.Text.Trim();
dr["user_age"] = txtAge.Text.Trim();
dr["user_id"] = txtNo.Text.Trim();
//实例化一个SqlCommandBuilder
SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(sda);
//调用其Update方法将DataTable更新到数据库中
sda.Update(dt);
}
//单击某条数据显示详细信息
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
txtAge.Text = dataGridView1.SelectedCells[3].Value.ToString();
txtName.Text = dataGridView1.SelectedCells[1].Value.ToString();
txtNo.Text = dataGridView1.SelectedCells[0].Value.ToString();
}
//在DataTable对象上可以多次使用Fill方法,如果主键存在,则传入行会与已有的匹配行合并。如果主键不存在,则传入行会追加到DataTable中
}
}
至此,数据操作执行完毕,第五步为DataSet数据集的介绍
第五步:DataSet数据集
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace DataSet数据集对象
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
/*第一部分:SetData数据集对象概述
它其实就像一个存放在内存中的小型数据库
它可以包含数据表,数据列,数据行,视图,约束以及关系
通常,DataSet数据源于数据库或者XML,为了从数据库中获取数据,需要使用数据适配器DataAdapter从数据库中查询数据
*/
//使用数据适配器DataAdapter从数据库中查询数据,调用其Fill方法填充DataSet对象
/*
conn=new SqlConnection("server=.;database=db_myr;uid=sa;pwd=***********");
DataSet ds=new DataSet(); //1.创建一个DataSet
SqlDataAdapter sda=new SqlDataAdapter("select * from tb_user",conn); //2.创建一个SqlDataAdapter
sda.Fill(ds); //3.使用Fill方法填充
*/
//第二部分:合并DataSet内容
/*
使用DataSet的Merge方法将DataSet,DataTable,DataRow数组中的内容合并到现有的DataSet中
Merge方法将指定DataSet及其及其架构与当前的DataSet合并,在此过程中,将根据给定的参数保留或放弃在当前DataSet中的更改并且处理不兼容的架构
public void Merge(DataSet dataSet,
bool preserveChanges,
MissingSchemaAction missingSchemaAction)
dataSet:其数据和架构会被合并到DataSet中
preserveChanges:要保留当前DataSet中的更改,则为true,否则为false
missingSchemaAction:MissingSchemaAction的枚举值之一
其枚举值有:
Add:添加必须的列以完成架构
AddWithKey:添加必须的列和主键信息以完成架构,用户可以在每一个DataTable上显示设置主键约束。这将确保对与现有记录匹配的传入记录进行更新,而不是追加
Error:如果缺少指定的列映射,则生成InvalidOperationException
Ignore:忽略格外列
当DataSet对象为null时,无法进行合并
*/
DataSet ds1 = new DataSet();
private void form1_Load(object sender, EventArgs e)
{
//实例化数据连接
SqlConnection conn = new SqlConnection("server=.;database=db_myr;uid=sa;pwd=*********");
//创建两个DataSet
DataSet ds = new DataSet();
//创建一个SqlDataAdapter对象
SqlDataAdapter sda = new SqlDataAdapter("select * from tb_user",conn);
//使用Fill方法填充DataSet
sda.Fill(ds);
SqlDataAdapter sda1 = new SqlDataAdapter("select * from tb_deptno", conn);
//创建一个SqlCommandBuilder对象
SqlCommandBuilder sbl = new SqlCommandBuilder(sda1);
//使用Fill方法填充DataSet
sda1.Fill(ds1);
//使用Merge方法将ds合并到ds1中
ds1.Merge(ds, true, MissingSchemaAction.AddWithKey);
//设置dataGridView控件的数据源
dataGridView1.DataSource = ds1.Tables[0];
}
//第三部分:复制DataSet内容
/*创建DataSet副本时:
创建DataSet原样副本,其中包含架构,数据,行状态信息和行版本。
创建包含现有DataSet的架构但仅包含已经修改行的DataSet.可以反回已经修改的所有行或者指定特定的DataRowState.有关行状态的更多信息,可参见行状态与行版本。
仅复制DataSet的架构(即关系结构),而不复制任何行。可以使用ImportRow将行导入现有的DataTable。
Copy方法复制DataSet的结构和数据. public DataSet Copy()
*/
//复制DataSet
private void button1_Click(object sender, EventArgs e)
{
DataSet ds2 = ds1.Copy();
dataGridView2.DataSource = ds1.Tables[0];
}
}
}