在 C# 语言中 ADO.NET 是在 ADO 的基础上发展起来的,ADO (Active Data Object) 是一个 COM 组件类库,用于访问数据库,而 ADO.NET 是在 .NET 平台上访问数据库的组件。
ADO.NET 是以 ODBC (Open Database Connectivity) 技术的方式来访问数据库的一种技术。
ADO.NET 中的常用命名空间如下表所示。
命名空间 数据提供程序
System.Data.SqlClient Microsoft SQL Server
System.Data.Odbc ODBC
System.Data.OracleClient Oracle
System.Data.OleDb OLE DB
在使用 ADO.NET 进行数据库操作时通常会用到 5 个类,分别是 Connection 类、 Command 类、DataReader 类、DataAdapter 类、DataSet 类。
在接下来的讲解中我们将以连接 SQL Server 为例介绍 ADO.NET 中的对象,引用的命名空间为 System.Data.SqlClient。
除了 DataSet 类以外,其他对象的前面都加上 Sql,即 SqlConnection、SqlCommand、SqlDataReader、SqlDataAdapter。
该类主要用于数据库中建立连接和断开连接的操作,并且能通过该类获取当前数据库连接的状态。
使用 Connection 类根据数据库的连接串能连接任意数据库,例如 SQLServer、Oracle、MySQL 等。
但是在 .NET 平台下,由于提供了一个 SQL Server 数据库,并额外提供了一些操作菜单便于操作,所以推荐使用 SQLServer 数据库。
该类主要对数据库执行增加、删除、修改以及查询的操作。
通过在 Command 类的对象中传入不同的 SQL 语句,并调用相应的方法来执行 SQL 语句。
该类用于读取从数据库中查询出来的数据,但在读取数据时仅能向前读不能向后读, 并且不能修改该类对象中的值。
在与数据库的连接中断时,该类对象中的值也随之被清除。
该类与 DataSet 联用,它主要用于将数据库的结果运送到 DataSet 中保存。
DataAdapter 可以看作是数据库与 DataSet 的一个桥梁,不仅可以将数据库中的操作结果运送到 DataSet 中,也能将更改后的 DataSet 保存到数据库中。
该类与 DataReader 类似,都用于存放对数据库查询的结果。
不同的是,DataSet 类中的值不仅可以重复多次读取,还可以通过更改 DataSet 中的值更改数据库中的值。
此外,DataSet 类中的值在数据库断开连接的情况下依然可以保留原来的值。
C# 语言中 Connection 类是 ADO.NET 组件连接数据库时第一个要使用的类,也是通过编程访问数据库的第一步。
接下来我们来了解一下 Connection 类中的常用属性和方法,以及如何连接 SQL Server 数据库。
Connection 类概述
Connection 类根据要访问的数据和访问方式不同,使用的命名空间也不同,类名也稍有区别,在这里我们使用的是 SqlConnection 类,以及微软提供的 SQL Server 2014 数据库。
SqlConnection 类中提供的常用属性和方法如下表所示。
属性或方法 | 说明 |
---|---|
SqlConnection() | 无参构造方法 |
SqlConnection(string connectionstring) | 带参数的构造方法,数据库连接字符串作为参数 |
Connectionstring | 属性,获取或设置数据库的连接串 |
State | 属性,获取当前数据库的状态,由枚举类型 Connectionstate 为其提供值 |
ConnectionTimeout | 属性,获取在尝试连接时终止尝试并生成错误之前所等待的时间 |
DataSource | 属性,获取要连接的 SQL Server 的实例名 |
Open() | 方法,打开一个数据库连接 |
Close() | 方法,关闭数据库连接 |
BeginTransaction() | 方法,开始一个数据库事务 |
使用 Connection 类连接数据库
在使用 Connection 类连接 SQL Server 2014 时,先要编写数据库连接串。
数据库连接串的书写方法有很多,这里介绍两种常用的方法。
第1种方式
server = 服务器名称 / 数据库的实例名 ; uid = 登录名 ; pwd = 密码 ; database = 数据库名称
其中:
server:用于指定要访问数据库的数据库实例名,服务器名称可以换成 IP 地址或者数据库所在的计算机名称,如果访问的是本机数据库,则可以使用“.”来代替,如果使用的是默认的数据库实例名,则可以省略数据库实例名。例如连接的是本机的默认数据库,则可以写成“server = .”。
uid:登录到指定 SQL Server 数据库实例的用户名,相当于以 SQL Server 身份验证方式登录数据库时使用的用户名,例如 sa 用户。
pwd:与 uid 用户对应的密码。
database:要访问数据库实例下的数据库名。
第2种方式
Data Source = 服务器名称 \ 数据库实例名 ; Initial Catalog = 数据库名称 ; User ID = 用户名 ; Password = 密码
其中:
Data Source:与第1种连接串写法中的 server 属性的写法一样,用于指定数据库所在的服务器名称和数据库实例名,如果连接的是本机的默认数据库实例,则写成“Data Source=. ”的形式。
Initial Catalog:与第 1 种连接串写法中的 database 属性的写法一样,用于指定在 Data Source 中数据库实例下的数据库名。
User ID:与第 1 种连接串写法中的 uid 属性的写法一样,用于指定登录数据库的用户名。
Password:与第 1 种连接串写法中的 pwd 属性的写法一样,用于指定 User ID 用户名所对应的密码。
此外,
还可以在连接字符串中使用 Integrate Security = True 的属性,省略用户名和密码,即以 Windows 身份验证方式登录 SQL Server 数据库。
将数据库连接更改如下:
Data Source = 服务器名称 \ 数据库实例名 ; Initial Catalog = 数据库名称 ; Integrate Security = True
需要注意的是,由于在使用 Windows 身份验证的方式登录数据库时,会对数据库的安全性造成一定的影响,因此不建议使用 Windows 身份验证的方法,而是使用 SQL Server 验证方式登录数据库,即指定用户名和密码。
提示:在 SQL Server 2014 中更改数据库的身份验证方式并不复杂,只需要在 SQL Server 的 SQL Server Management Studio 2014 中右击数据库的服务器结点,弹出如下图所示的服务器属性界面,并在界面中选择“安全性”选项。
服务器属性界面
在该界面中可以通过选择“服务器身份验证”中的两个选项来切换身份验证方式,默认情况下选中“Windows 身份验证模式”。
在选中任意一种身份验证模式后需要重启 SQL Server 服务器才能完成服务器身份验证模式的更改。
在完成了数据库连接串的编写后即可使用 SqlConnection 类与数据库连接,分以下 3 步完成。
SqlConnection 连接对象名 = new SqlConnection( 数据库连接串 );
在使用 Open 方法打开数据库连接时,如果数据库的连接串不正确或者数据库的服务处于关闭状态,会出现打开数据库失败的相关异常,因此需要通过异常处理来处理异常。
打开数据库连接的语句形式如下。
连接对象名.Open();
关闭数据库连接的语句形式如下。
连接对象名.Close();
如果在打开数据库连接时使用了异常处理,则将关闭数据库连接的语句放到异常处理的 finally 语句中,这样能保证无论是否发生了异常都将数据库连接断开,以释放资源。
除了使用异常处理的方式释放资源外,还可以使用 using 的方式释放资源。
具体的语句如下。
using(SqlConnection 连接对象名 = new SQLConnection( 数据库连接串 ))
{
//打开数据库连接
//对数据库先关操作的语句
}
using 关键字的用法主要有两个,一个是引用命名空间,一个是创建非托管资源对象。
在 .NET 平台上资源分为托管资源和非托管资源,托管资源是由 .NET 框架直接提供对其资源在内存中的管理,例如声明的变量;非托管资源则不能直接由 .NET 框架对其管理,需要使用代码来释放资源,例如数据库资源、操作系统资源等。
下面通过实例来演示 SqlConnection 类的使用。
【实例 1】创建与本机 SQL Server 数据库的连接,并使用异常处理。
根据题目要求,连接 SQL Server 数据库时使用的用户名为 sa、密码为 pwdpwd,连接的数据库为test。
创建 Windows 窗体应用程序,并在窗体上放置一个按钮,在按钮的单击事件中加入以下代码。
//编写数据库连接串
string connStr = "Data source=.;Initial Catalog=test;User ID=sa;Password=pwdpwd";
//创建SqlConnection的实例
SqlConnection conn = null;
try
{
conn = new SqlConnection(connStr);
//打开数据库连接
conn.Open();
MessageBox.Show("数据库连接成功!");
}
catch(Exception ex)
{
MessageBox.Show("数据库连接失败!" + ex.Message);
}
finally
{
if (conn != null)
{
//关闭数据库连接
conn.Close();
}
}
执行上面的代码,效果如下图所示。
测试数据库连接
从上面的执行效果可以看出,数据库已经成功。
【实例 2】在上一实例的基础上使用 using 关键字释放资源。
根据题目要求,省略了 finally 部分的语句,代码如下。
纯文本复制
//编写数据库连接串在这里插入代码片
string connStr = "Data source=.;Initial Catalog=test;User ID=sa;Password=pwdpwd";
//创建SqlConnection的实例
try
{
using(SqlConnection conn=new SqlConnection(connStr))
{
//打开数据库连接
conn.Open();
MessageBox.Show("数据库连接成功!");
}
}
catch(Exception ex)
{
MessageBox.Show("数据库连接失败!" + ex.Message);
}
执行上面的代码,效果与上一实例—样。
操作数据库需则要用到 Command 类中提供的属性和方法。下面来介绍一下如何使用 Command 类来操作数据表中的数据。
Command 类概述
在 System.Data.SqlClient 命名空间下,对应的 Command 类为 SqlCommand,在创建 SqlCommand 实例前必须已经创建了与数据库的连接。
SqlCommand 类中常用的构造方法如下表所示。
构造方法 说明
SqlCommand() 无参构造方法
SqlCommand(string commandText,SqlConnection conn) 带参的构造方法,第 1 个参数是要执行的 SQL 语句,第 2 个参数是数据库的连接对象
对数据库中对象的操作不仅包括对数据表的操作,还包括对数据库、视图、存储过程等数据库对象的操作,接下来主要介绍的是对数据表和存储过程的操作。
在对不同数据库对象进行操作时,SqlCommand 类提供了不同的属性和方法,常用的属性和方法如下表所示。
属性或方法 | 说明 |
---|---|
CommandText | 属性,Command 对象中要执行的 SQL 语句 |
Connection | 属性,获取或设置数据库的连接对象 |
CommandType | 属性,获取或设置命令类型 |
Parameters | 属性,设置 Command 对象中 SQL 语句的参数 |
ExecuteReader() | 方法,获取执行查询语句的结果 |
ExecuteScalar() | 方法,返回查询结果中第 1 行第 1 列的值 |
ExecuteNonQuery() | 方法,执行对数据表的增加、删除、修改操作 |
使用 Command 类操作数据库
Command 类中提供了 3 种命令类型,分别是 Text、TableDirect 以及 StoredProcedure,默认情况下是 Text。
所谓 Text 类型是指使用 SQL 语句的形式,包括增加、删除、修改以及查询的SQL语句。
StoredProcedure 用于执行存储过程;TableDirect 仅在 OLE DB 驱动程序中有效。
在使用 Command 类操作数据库时需要通过以下步骤完成。
创建 SqlCommand 类的实例分两种情况,一种是命令类型为 Text 的,一种是命令类型为 StoredProcedure 的。
命令类型为 Text
SqlCommand SqlCommand 类的实例名 = new SqlCommand( SQL 语句 , 数据库连接类的实例 );
其中:
SQL 语句:指该 SqlCommand 类的实例要执行的 SQL 语句。
数据库连接类的实例:指使用 SqlConnection 类创建的实例,通常数据库连接类的实例处于打开的状态。
命令类型为 StoredProcedure
SqlCommand SqlCommand 类的实例名 = new SqlCommand( 存储过程名称 , 数据库连接类的实例 );
需要注意的是,存储过程必须是当前数据库实例中的存储过程,并且在调用带参数的存储过程时,还需要在 SqlCommand 类的实例中添加对应的存储过程参数。
为存储过程添加参数,需要使用 SqlCommand 类实例的 Parameters 属性来设置,具体的代码如下。
SqlCommand 类实例 .Parameters.Add( 参数名 , 参数值 );
在这里,参数名与存储过程中定义的参数名要一致。
2) 执行对数据表的操作
在执行对数据表的操作时通常分为两种情况,一种是执行非查询 SQL 语句的操作,即增加、修改、删除的操作,一种是执行查询 SQL 语句的操作。
执行非查询 SQL 语句的操作
在执行非查询 SQL 语句时并不需要返回表中的数据,直接使用 SqlCommand 类的 ExecuteNonQuery 方法即可,该方法的返回值是一个整数,用于返回 SqlCommand 类在执行 SQL 语句后,对表中数据影响的行数。
当该方法的返回值为 -1 时,代表 SQL 语句执行失败,当该方法的返回值为 0 时,代表 SQL 语句对当前数据表中的数据没有影响。
例如 要删除学号为 1100 的学生的信息,而表中不存在该学号的学生的信息,SQL语句可以正常执行,但对表中的影响行数是 0。
具体的代码如下。
SqlCommand 类的实例 .ExecuteNonQuery();
需要注意的是,如果执行的 SQL 语句在数据库中执行错误,则会产生异常,因此该部分需要进行异常处理。
执行查询语句的操作
在执行查询语句时通常需要返回查询结果,SqlCommand 类中提供的 ExecuteReader 方法在执行查询 SQL 语句后,会返回一个 SqlDataReader 类型的值,通过遍历 SqlDataReader 类中的结果即可得到返回值。
具体的代码如下。
SqlDataReader dr = SqlCommand 类的实例 .ExecuteReader();
此外,如果在执行查询语句后并不需要返回所有的查询结果,而仅需要返回一个值,例如查询表中的记录行数,这时可以使用 ExecuteScalar 方法。具体的代码如下。
int returnvalue = SqlCommand 类的实例 .ExecuteScalar();
下面通过实例来演示 SqlCommand 类的使用。
【实例 1】制作一个用户注册界面,使用 SqlCommand 类向用户信息表中添加一条记录。
根据题目要求,先在 SQL Server 2014 中创建用户信息表 userinfo,SQL 语句如下。
create table userinfo
(
id int identity(1,1) primary key,
name varchar(20),
password varchar(20)
)
为了方便,将表中的 id 设置为主键,并设置为标识列,以保证值的唯一性。
使用 SqlCommand 类向表中添加数据的语句如下。
//“注册”按钮的单击事件
private void button1_Click(object sender, EventArgs e)
{
//编写数据库连接串
string connStr = "Data Source=.;Initial Catalog=test;User ID=sa;Password=root";
//创建 SqlConnection的实例
SqlConnection conn = null;
try
{
conn = new SqlConnection(connStr);
//打开数据库连接
conn.Open();
string sql = "insert into userinfo(name,password) values('{0}','{1}')";
//填充SQL语句
sql = string.Format(sql, textBox1.Text, textBox2.Text);
//创建SqlCommand对象
SqlCommand cmd = new SqlCommand(sql, conn);
//执行SQL语句
int returnvalue = cmd.ExecuteNonQuery();
//判断SQL语句是否执行成功
if(returnvalue != -1)
{
MessageBox.Show("注册成功!");
}
}
catch(Exception ex)
{
MessageBox.Show("注册失败!"+ex.Message);
}
finally
{
if (conn != null)
{
//关闭数据库连接
conn.Close();
}
}
}
运行窗体,效果如下图所示。
用户注册
从上面的运行效果可以看出,通过 SqlCommand 对象已经将用户信息添加到数据表 userinfo 中。
【实例 2】制作一个登录界面,使用 SqlCommand 类判断用户是否登录成功。
根据题目要求,登录功能通过查询语句来实现,即将界面上输入的用户名和密码与数据表中存储的用户信息相比较,如果有与之匹配的用户信息则弹出消息框提示登录成功, 否则提示登录失败。
实现登录功能的界面如下图所示。
登录界面
在登录界面中的“登录”按钮的单击事件中实现用户登录功能,并在“取消”按钮的单击事件中实现关闭登录窗体的功能。
实现的代码如下。
//"登录"按钮的单击事件
private void button1_Click(object sender, EventArgs e)
{
//编写数据库连接串
string connStr = "Data Source=.;Initial Catalog=test;User ID=sa;Password=root";
//创建SQLConnection的实例
SqlConnection conn = null;
try
{
conn = new SqlConnection(connStr);
//打开数据库连接
conn.Open();
string sql = "Select count(*) from userinfo where name='{0}' and password='{1}'";
//填充SQL语句
sql = string.Format(sql, textBox1.Text, textBox2.Text);
//创建SqlCommand对象
SqlCommand cmd = new SqlCommand(sql, conn);
//执行SQL语句
int returnvalue = (int)cmd.ExecuteScalar();
//判断SQL语句是否执行成功
if (returnvalue != 0)
{
MessageBox.Show("登录成功!");
}
else
{
MessageBox.Show("登录失败!");
}
}
catch (Exception ex)
{
MessageBox.Show("注册失败!" + ex.Message);
}
finally
{
if (conn != null)
{
//关闭数据库连接
conn.Close();
}
}
}
//“取消”按钮的单击事件
private void button2_Click(object sender, EventArgs e)
{
this.Close();
}
运行该窗体,效果如下图所示。
登录成功效果
从上面的运行效果可以看出,通过使用 SqlCommand 类中的 ExecuteScalar 方法即可判断是否存在界面中输入的用户名和密码。
【实例 3】改进用户注册功能,使用户在注册时用户名唯一。
在上一实例的登录功能中有可能出现不同的人注册时的用户名和密码相同的情况,因此很难判断究竟是哪个用户登录。
在很多软件中,用户注册功能都会判断用户名是否唯一,或者直接使用邮箱或手机号作为登录名。
下面在实例 1 的注册功能中添加判断用户名是否唯一的功能,实现的代码如下。
//“注册”按钮的单击事件
private void button1_Click(object sender, EventArgs e)
{
//编写数据库连接串
string connStr = "Data Source=.;Initial Catalog=test;User ID=sa;Password=root";
//创建 SqlConnection的实例
SqlConnection conn = null;
try
{
conn = new SqlConnection(connStr);
//打开数据库连接
conn.Open();
//判断用户名是否重复
string checkNameSql = "select count(*) from userinfo where name='{0}'";
checkNameSql = string.Format(checkNameSql, textBox1.Text);
//创建SqlCommand对象
SqlCommand cmdCheckName = new SqlCommand(checkNameSql, conn);
//执行SQL语句
int isRepeatName = (int)cmdCheckName.ExecuteScalar();
if (isRepeatName != 0)
{
//用户名重复,则不执行注册操作
MessageBox.Show("用户名已存在!");
return;
}
string sql = "insert into userinfo(name,password) values('{0}','{1}')";
//填充SQL语句
sql = string.Format(sql, textBox1.Text, textBox2.Text);
//创建SqlCommand对象
SqlCommand cmd = new SqlCommand(sql, conn);
//执行SQL语句
int returnvalue = cmd.ExecuteNonQuery();
//判断SQL语句是否执行成功
if(returnvalue != -1)
{
MessageBox.Show("注册成功!");
}
}
catch(Exception ex)
{
MessageBox.Show("注册失败!"+ex.Message);
}
finally
{
if (conn != null)
{
//关闭数据库连接
conn.Close();
}
}
}
运行该窗体,输入已经存在的用户名“张三”,执行效果如下图。
注册同名用户时的效果
从上面的运行效果可以看出,由于“张三”用户在表中已经存在,所以在注册时会弹出“用户名已存在!”的提示。
【实例 4】创建一个存储过程实现用户注册功能,并使用 SqlCommand 类调用存储过程。
用户注册功能的存储过程比较简单,只需要写一个带参数的存储过程将用户名和密码传递给存储过程,并使用 insert 语句将用户名和密码添加到用户信息表中。
在存储过程中暂不考虑判断用户名是否重复。创建存储过程的语句如下。
create procedure AddUser(@name varchar(20), @password varchar(20))
as
begin
insert into userinfo (name, password) values (@name, @password);
end
注册页面与实例 1 一样,在“注册”按钮的单击事件中调用 AddUser 存储过程,代码如下。
//编写数据库连接串
string connStr = "Data Source=.;Initial Catalog=test;User ID=sa;Password=root";
//创建 SqlConnection的实例
SqlConnection conn = null;
try
{
conn = new SqlConnection(connStr);
//打开数据库连接
conn.Open();
//创建SqlCommand对象
SqlCommand cmd = new SqlCommand("AddUser", conn);
//设置SQLCommand对象的命令类型(CommandType)是存储过程
cmd.CommandType = CommandType.StoredProcedure;
//设置存储过程需要的参数
cmd.Parameters.AddWithValue("name", textBox1.Text);
cmd.Parameters.AddWithValue("password", textBox2.Text);
//执行存储过程
int returnvalue = cmd.ExecuteNonQuery();
Console.WriteLine(returnvalue);
//判断SQL语句是否执行成功
if(returnvalue != -1)
{
MessageBox.Show("注册成功!");
}
}
catch(Exception ex)
{
MessageBox.Show("注册失败!"+ex.Message);
}
finally
{
if (conn != null)
{
//关闭数据库连接
conn.Close();
}
}
运行该窗体,效果与实例 1 一致。从上面的代码可以看出,调用存储过程并不复杂,只需要在 SqlCommand 对象中将 CommandType 属性的值改成 StoredProcedure,并添加存储过程中所需要的参数即可。
在 C# 中 DataReader 类的作用是读取查询结果,与在《C# Command》一节中介绍的 Command 类中的 ExecuteReader 方法一起使用。
下面来介绍一下 DataReader 类中常用的属性和方法,以及如何使用该类查询表中的数据。
DataReader 类概述
DataReader 类在 System.Data.SqlClient 命名空间中,对应的类是 SqlDataReader,主要用于读取表中的查询结果,并且是以只读方式读取的(即不能修改 DataReader 中存放的数据)。
正是由于 DataReader 类的特殊的读取方式,其访问数据的速度比较快,占用的服务器资源比较少。
SqlDataReader 类中常用的属性和方法如下表所示。
属性或方法 | 说明 |
---|---|
FieldCount | 属性,获取当前行中的列数 |
HasRows | 属性,获取 DataReader 中是否包含数据 |
IsClosed | 属性,获取 DataReader 的状态是否为已经被关闭 |
Read | 方法,让 DataReader 对象前进到下一条记录 |
Close | 方法,关闭 DataReader 对象 |
Get XXX (int i) | 方法,获取指定列的值,其中XXX代表的是数据类型。例如获取当前行第1列 double 类型的值,获取方法为GetDouble(o) |
使用 DataReader 类读取查询结果
在使用 DataReader 类读取查询结果时需要注意,当查询结果仅为一条时,可以使用 if 语句查询 DataReader 对象中的数据,如果返回值是多条数据,需要通过 while 语句遍历 DataReader 对象中的数据。
在使用 DataReader 类读取查询结果时需要通过以下步骤完成:
SqlDataReader dr=SqlCommand 类实例 .ExecuteReader();
SqlDataReader 类中提供的 Read 方法用于判断其是否有值,并指向 SqlDataReader 结果中的下一条记录。
dr.Read()
如果返回值为 True,则可以读取该条记录,否则无法读取。
在读取记录时,要根据表中的数据类型来读取表中相应的列。
dr.Close()
下面通过实例来演示 SqlDataReader 类的使用。
【实例】根据用户姓名查询用户的编号和密码,并将编号和密码显示在标签控件 (Label) 上。
根据姓名查询用户信息的界面如下图所示。
根据用户名查询用户信息
在该界面中默认情况下显示“没有符合条件的结果”,如果根据文本框中输入的用户名能查询到指定用户的信息,则将默认文字替换成用户编号和密码。
实现该功能的代码 如下。
//“查询”按钮单击事件
private void button1_Click(object sender, EventArgs e)
{
//编写数据库连接串
string connStr = "Data Source=.;Initial Catalog=test;User ID=sa;Password=root";
//创建 SqlConnection的实例
SqlConnection conn = null;
//定义SqlDataReader类的对象
SqlDataReader dr = null;
try
{
conn = new SqlConnection(connStr);
//打开数据库连接
conn.Open();
string sql = "select id,password from userinfo where name='{0}'";
//填充SQL语句
sql = string.Format(sql, textBox1.Text);
//创建SqlCommand对象
SqlCommand cmd = new SqlCommand(sql, conn);
//执行Sql语句
dr = cmd.ExecuteReader();
//判断SQL语句是否执行成功
if (dr.Read())
{
//读取指定用户名对应的用户编号和密码
string msg = "用户编号:" + dr[0] + " 密码:" + dr[1];
//将msg的值显示在标签上
label2.Text = msg;
}
}
catch (Exception ex)
{
MessageBox.Show("查询失败!" + ex.Message);
}
finally
{
if (dr != null)
{
//判断dr不为空,关闭SqlDataReader对象
dr.Close();
}
if (conn != null)
{
//关闭数据库连接
conn.Close();
}
}
}
运行该窗体,效果如下图所示。
查询用户名为“张三”的用户信息
从上面的运行效果可以看出,“张三”用户对应的用户编号为 1、密码为 123456。
需要注意的是,实现上述功能的要求是用户表中的用户名是唯一的,以避免出现查询错误
在执行对表中数据的查询时还能将数据保存到 DataSet 中,但需要借助 DataAdapter 类来实现。
在实际应用中,DataAdapter 与 DataSet 是在查询操作中使用最多的类。
此外,还可以通过 DataSet 实现对表中数据的增加、修改、删除操作。
DataAdapter 与 DataSet 类简介
DataAdapter 类用于将数据表中的数据查询出来并添加到 DataSet 中,DataAdapter 在 System.Data.SqlClient 命名空间下对应的类名是 SqlDataAdapter。
SqlDataAdapter 类的主要构造方法如下表所示。
构造方法 | 说明 |
---|---|
SqlDataAdapter(SqlCommand cmd) | 带参数的构造方法,传递 SqlCommand 类的对象作为参数 |
SqlDataAdapter(string sql, SqlConnection conn) | 带参数的构造方法,sql 参数是指定对数据表执行的 SQL 语句,conn 是数据库的连接对象 |
SqlDataAdapter() | 不带参数的构造方法 |
从 SqlDataAdapter 类的构造方法可以看出,SqlDataAdapter 类需要与 SqlCommand 类和 SqlConnection 类一起使用。
SqlDataAdapter 类常用的属性和方法如下表所示。
属性或方法 | 说明 |
---|---|
SelectCommand | 属性,设置 SqlDataAdapter 中要执行的查询语句 |
InsertCommand | 属性,设置 SqlDataAdapter 中要执行的添加语句 |
UpdateCommand | 属性,设置 SqlDataAdapter 中要执行的修改语句 |
DeleteCommand | 属性,设置 SqlDataAdapter 中要执行的删除语句 |
Fill(DataSet ds) | 方法,将 SqlDataAdapter 类中查询出的结果填充到 DataSet 对象中 |
Fill(DataTable dt) | 方法,将 SqlDataAdapter 类中查询出的结果填充到 DataTable 对象 中,DataTable是数据表对象,在一个DataSet对象中由多个 DataTable对象构成 |
Update(DataSet ds) | 方法,更新 DataSet 对象中的数据 |
Update(DataTable dt) | 方法,更新 DataTable 对象中的数据 |
DataSet 类是一种与数据库结构类似的数据集,每个 DataSet 都是由若干个数据表构成的,DataTable 即数据表,每个 DataTable 也都是由行和列构成的,行使用 DataRow 类表示、列使用 DataColumn 类表示。
此外,用户还可以通过 DataRelation 类设置数据表之间的关系。
下面介绍 DataSet 类以及 DataTable 类的使用。
1) DataSet 类
DataSet 类中的构造方法如下表所示。
构造方法 | 说明 |
---|---|
DataSet() | 无参构造方法 |
DataSet(string DataSetName) | 带参数的构造方法,DataSetName 参数用于指定数据集名称 |
DataSet 类中常用的属性和方法如下表所示。
属性或方法 | 说明 |
---|---|
Tables | 属性,获取 DataSet 中所有数据表的集合,Tables[0] 代表集合中的第一个数据表 |
CaseSensitive | 属性,获取或设置 DataSet 中的字符串是否区分大小写 |
Clear() | 方法,清空 DataSet 中的数据 |
Copy() | 方法,复制 DataSet 中的数据 |
AcceptChanges() | 方法,更新 DataSet 中的数据 |
HasChanges() | 方法,获取 DataSet 中是否有数据发生变化 |
RejectChanges() | 方法,撤销对 DataSet 中数据的更改 |
2) DataTable
DataTable 作为 DataSet 中的重要对象,其与数据表的定义是类似的,都是由行和列构成,并有唯一的表名。
从 SqlDataAdapter 类的填充方法 (Fill) 中可以看出允许将数据直接填充到 DataTable 中,这样既能节省存储空间也能简化查找数据表中的数据。
DataTable 中常用的构造方法如下表所示。
构造方法 | 说明 |
---|---|
DataTable() | 无参构造方法 |
DataTable(string TableName) | 带参数的构造方法, TableName 参数用于指定数据表的名称 |
DataTable 与 DataSet 有很多相似的属性和方法,在下表中列出了一些与 DataSet 类不同的属性。
属性 | 说明 |
---|---|
TableName | 属性,获取或设置 DataTable 的名称 |
Columns | 属性,获取 DataTable 中列的集合 |
Rows | 属性,获取 DataTable 中行的集合 |
DataSet | 属性,获取 DataTable 所在的 DataSet |
Constraints | 属性,获取 DataTable 中的所有约束 |
使用 DataSet 和 DataTable 类存放查询结果
在实际应用中,将查询结果存储到 DataSet 类或 DataTable 类中均可,在操作查询结果时也非常类似。
下面分别通过实例来演示 DataSet 和 DataTable 的使用。
【实例】创建 Windows 应用程序,查询用户信息表(userinfo)中的所有用户名,并将用户名显示在列表控件(ListBox)中。
根据题目要求,设置用户信息查询界面如下图所示。
用户名查询界面设计
单击“查询全部用户名”按钮,将所有用户名显示到 ListBox 控件中,首先使用 DataSet 对象存储查询结果,代码如下。
//“查询全部用户”按钮的单击事件
private void button1_Click(object sender, EventArgs e)
{
//编写数据库连接串
string connStr = "Data Source=.; Initial Catalog=test;User ID=sa;Password=root";
//创建 SQLConnection 的实例
SqlConnection conn = null;
try
{
conn = new SqlConnection(connStr);
//打开数据库连接
conn.Open();
string sql = "select name from userinfo";
//创建 SQLDataAdapter 类的对象
SqlDataAdapter sda = new SqlDataAdapter(sql, conn);
//创建DataSet类的对象
DataSet ds = new DataSet();
//使用SQLDataAdapter对象sda将查询结果填充到Dataset对象ds中
sda.Fill(ds);
//设置ListBox控件的数据源(DataSource)属性
listBox1.DataSource = ds.Tables[0];
//在listBox控件中显示name列的值
listBox1.DisplayMember = ds.Tables[0].Columns[0].ToString();
}
catch(Exception ex)
{
MessageBox.Show("查询失败!" + ex.Message);
}
finally
{
if (conn != null)
{
//关闭数据库连接
conn.Close();
}
}
}
运行该窗体,效果如下图所示。
查询全部用户名的效果
从上面的运行效果可以看出,已经将用户信息表 (userinfo) 中的所有用户名显示在列表控件 (ListBox) 中。
需要注意的是,ListBox 控件中的 DataSource 属性用于设置控件中内容的数据源,并需要通过 DisplayMember 属性来指定显示在 ListBox 控件中的内容。
在本实例中将 DataSet 对象换成 DataTable 对象,更改部分代码如下。
//创建 SqlDataAdapter 类的对象
SqlDataAdapter sda = new SqlDataAdapter(sql, conn);
//创建 DataTable 类的对象
DataTable dt = new DataTable();
//使用 SqlDataAdapter 对象 sda 将查询结果填充到 DataSet 对象 dt 中
sda.Fill(dt);
//设置 ListBox 控件的数据源(DataSource)属性
listBox1.DataSource = dt;
//在 ListBox 控件中显示 name 列的值
listBox1.DisplayMember = dt.Columns[0].ToStiring();
更改后再次运行窗体,效果与上图—样。
对于 Windows 应用程序中的控件,除了可以使用代码为其 DataSource 属性设置数据源外,也可以用 Windows 应用程序中所带的自动绑定功能实现。
在前面《C# Command》一节中已经介绍了使用 SqlCommand 对象中的 ExecuteNonQuery 方法执行非查询 SQL 语句来实现对数据表的更新操作,使用 DataSet 对象也能实现相同的功能, 并且能节省数据访问时间。
每个 DataSet 都是由多个 DataTable 构成的,更新 DataSet 中的数据实际上是通过更新 DataTable 来实现的。
每个 DataTable 对象都是由行 (DataRow) 和列 (DataColumn) 构成的,下面分别介绍 DataRow 类和 DataColumn 类的使用。
1) DataRow 类
DataRow 类代表数据表中的行,并允许通过该类直接对数据表进行添加、修改、删除行的操作。
DataRow 类中常用的属性和方法如下表所示。
属性或方法 | 说明 |
---|---|
Table | 属性,设置 DataRow 对象所创建 DataTable 的名称 |
RowState | 属性,获取当前行的状态 |
HasErrors | 属性,获取当前行是否存在错误 |
AcceptChanges() | 方法,更新 DataTable 中的值 |
RejectChanges() | 方法,撤销对 DataTable 中的值的更新 |
Delete() | 方法,标记当前的行被删除,并在执行 AcceptChanges 方法后更新数据表 |
在 DataRow 类中没有提供构造方法,需要通过 DataTable 中的 NewRow 方法创建 DataRow 类的对象,具体的语句如下。
DataTable dt = new DataTable();
DataRow dr = dt.NewRow();
这样,dr 即为新添加的行,每行数据是由多列构成的,如果在 DataTable 对象中已经存在表结构,则直接使用dr[ 编号或列名 ]= 值的形式即可为表中的列赋值。
2) DataColumn 类
DataColumn 类是数据表中的列对象,与数据库中表的列定义一样,都可以为其设置列名以及数据类型。
DataColumn类中常用的构造方法如下表所示。
构造方法 | 说明 |
---|---|
DataColumn() | 无参构造方法 |
DataColumn(string columnName) | 带参数的构造方法,columnName 参数代表的是列名 |
DataColumn(string columnName,Type dataType) | 带参数的构造方法,columnName 参数代表的是列名,dataType 参数代表的是列的数据类型 |
DataColumn 类提供了一些属性对 DataColumn 对象进行设置,常用的属性如下表所示。
属性 | 说明 |
---|---|
ColumnName | 属性,设置 DataColumn 对象的列名 |
DataType | 属性,设置 DataColumn 对象的数据类型 |
MaxLength | 属性,设置 DataColumn 对象值的最大长度 |
Caption | 属性,设置 DataColumn 对象在显示时的列名,类似于给表中的列设置别名 |
DefaultValue | 属性,设置 DataColumn 对象的默认值 |
AutoIncrement | 属性,设置 DataColumn 对象为自动增长列,与 SQL Server 中数据表的标识列类似 |
AutoIncrementSeed | 属性,与 AutoIncrement 属性联用,用于设置自动增长列的初始值 |
AutoIncrementStep | 属性,与 AutoIncrement 属性联用,用于设置自动增长列每次增加的值 |
Unique | 属性,设置 DataColumn 对象的值是唯一的,类似于数据表的唯一约束 |
AllowDBNull | 属性,设置 DataColumn 对象的值是否允许为空 |
下面通过实例来演示 DataRow 类和 DataColumn 类的使用。
【实例】通过 DataRow 类、DataColumn 类以及 DataTable 类设计专业信息表,并向该表中添加专业,在 ListBox 控件中显示所有专业信息。
专业信息表的列包括专业编号、专业名称,要求专业编号是自动增长列,专业名称是唯一值。
创建 Windows 应用程序,添加专业信息并查询的界面设计如下图所示。
添加专业信息并查询的界面设计
在每次新添加专业名称时将新的专业添加到ListBox控件中,实现的代码如下。
public partial class DataRowform : Form
{
//创建DataTable类的对象其表明为major
private DataTable dt = new DataTable("major");
//在构造方法中初始化DataTable对象,设置DataTable 中的列
public DataRowform()
{
InitializeComponent();
//创建专业编号列,列明为id 、数据类型为整型
DataColumn id = new DataColumn("id", typeof(int));
//设置id为自动增长列
id.AutoIncrement = true;
//设置id的初始值
id.AutoIncrementSeed = 1;
//设置id每次增长的值
id.AutoIncrementStep = 1;
//将id列加入到DataTable中
dt.Columns.Add(id);
//创建专业名称列,列明为name,数据类型为字符串类型
DataColumn name = new DataColumn("name", typeof(string));
//设置name列的值是唯一的
name.Unique = true;
//将name列加入到DataTable 对象中
dt.Columns.Add(name);
}
//添加按钮的单击事件
private void button1_Click(object sender, EventArgs e)
{
//向DataTable中天加一行,创建DataRow对象
DataRow dr = dt.NewRow();
//添加专业名称列的值
dr["name"] = textBox1.Text;
//将DataRow添加到DataTable对象中
dt.Rows.Add(dr);
//设置ListBox控件中的DataSource属性
listBox1.DataSource = dt;
//设置在listBox控件中显示的列
listBox1.DisplayMember = dt.Columns["name"].ToString();
}
}
运行该窗体,效果如下图所示。
使用DataTable添加和查询专业信息
从上面的运行效果可以看出,DataTable 类的使用与直接设计数据库中的表是类似的,只是没有将数据存储到数据库中。
既然使用 DataTable 类能完成与表设计和操作相同的功能,那么通过更新 DataTable 来更新数据库中的数据表效果会事半功倍,并能在离线状态下保存数据。
在 C# 语言中使用 DataSet 类更新数据库中的数据,还需要使用 System.Data.SqlClient 命名空间中的 SqlCommandBuilder 类自动生成 SqlDataAdapter 对象的添加、修改以及删除方法。
在与 SqlDataAdapter 类联用时,只需要在创建 SqlCommandBuilder 类的实例时使用 SqlDataAdapter 对象作为参数即可,语法形式如下。
SqlCommandBuilder 对象名 = new SqlCommandBuilder(SqlDataAdapter 类的对象 );
下面通过实例来演示如何使用 DataSet 更新数据库。
【实例 1】使用 DataSet 实现用户注册功能。
根据题目要求在“注册”按钮的单击事件中使用 DataSet 向表中添加用户信息。实现的代码如下。
//注册按钮的单击事件
private void button1_Click(object sender, EventArgs e)
{
//数据库连接串
string connStr = "Data Source=.;Initial Catalog=test;User ID=sa;Password=root";
//创建SQLConnection的实例
SqlConnection conn = null;
try
{
conn = new SqlConnection(connStr);
//打开数据库连接
conn.Open();
string sql = "select * from userinfo";
//创建SqlDataAdapter类的对象
SqlDataAdapter sda = new SqlDataAdapter(sql, conn);
//创建DataSet类的对象
DataSet ds = new DataSet();
//使用SQLDataAdapter对象sda将查询结果填充到DataTable对象ds中
sda.Fill(ds);
//创建SqlCommandBuilder类的对象
SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(sda);
//创建DataRow类的对象
DataRow dr = ds.Tables[0].NewRow();
//设置name列的值
dr["name"] = textBox1.Text;
//设置password列的值
dr["password"] = textBox2.Text;
//向DataTable对象中添加一行
ds.Tables[0].Rows.Add(dr);
//更新数据库
sda.Update(ds);
MessageBox.Show("注册成功!");
}
catch(Exception ex)
{
MessageBox.Show("注册失败!"+ex.Message);
}
finally
{
if (conn != null)
{
//关闭数据库连接
conn.Close();
}
}
}
运行该窗体,输入用户名和密码,单击“注册”按钮后即可将用户信息添加到数据表中。
将上述代码中的 DataSet 类换成 DataTable 类也能完成同样的功能,并可以简化代码。
使用 DataTable 类完成上面的功能,将 DataSet 替换成 DataTable 的部分代码如下。
//创建 DataTable 类的对象
DataTable dt=new DataTable();
//使用 SqlDataAdapter 对象 sda 将查询结果填充到 DataTable 对象 dt 中
sda.Fill(dt);
//创建 SqlCommandBuilder 类的对象
SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(sda);
/ /创建 DataRow 类的对象
DataRow dr=dt.NewRow();
//设置name列的值
dr["name"] = txtName.Text;
//设置password列的值
dr["password"] = txtPwd.Text;
//向DataTable对象中添加一行
dt.Rows.Add(dr);
//更新数据库
sda.Update(dt);
【实例 2】使用 DataSet 实现更改用户密码的功能。
根据题目要求,在界面上通过文本框输入用户名、原密码以及新密码更新用户密码,界面设计如下图所示。
修改密码功能的界面
在“确认”按钮的单击事件中实现密码的修改操作,代码如下。
//确认按钮的单击事件
private void button1_Click(object sender, EventArgs e)
{
//数据库连接串
string connStr = "Data Source=.;Initial Catalog=test;User ID=sa;Password=root";
//创建SQLConnection的实例
SqlConnection conn = null;
try
{
conn = new SqlConnection(connStr);
//打开数据库连接
conn.Open();
string sql = "select * from userinfo where name='{0}' and password='{1}'";
//填充SQL语句
sql = string.Format(sql, textBox1.Text, textBox2.Text);
//创建SqlDataAdapter类的对象
SqlDataAdapter sda = new SqlDataAdapter(sql, conn);
//创建DataSet类的对象
DataSet ds = new DataSet();
//使用SQLDataAdapter对象sda将查询结果填充到DataTable对象ds中
sda.Fill(ds);
if (ds.Tables[0].Rows.Count == 1)
{
//判断新密码不能为空,以及判断两次输入的密码一致
if (!"".Equals(textBox3.Text) && textBox3.Text.Equals(textBox4.Text))
{
//创建SqlCommandBuilder类的对象
SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(sda);
//创建DataRow类的对象
DataRow dr = ds.Tables[0].Rows[0];
//设置password列的值
dr["password"] = textBox3.Text;
//更新数据库
sda.Update(ds);
//更新DataSet对象中的数据
ds.Tables[0].AcceptChanges();
MessageBox.Show("密码修改成功!");
}
else
{
MessageBox.Show("新密码为空或者两侧输入的密码不一致!");
}
}
}
catch(Exception ex)
{
MessageBox.Show("密码修改失败!"+ex.Message);
}
finally
{
if (conn != null)
{
//关闭数据库连接
conn.Close();
}
}
}
运行该窗体,效果如下图所示。
修改密码成功的效果
从上面的运行效果可以看出密码修改成功,也可以在数据库中查看用户信息表 (userinfo) 的数据验证密码是否被修改。
如果需要通过 DataSet 删除数据表中的数据,则使用以下代码即可。
纯文本复制
//删除 DataTable 中的指定行,ds代表DataSet对象
ds.Tables[0].Rows[ 行数 ].Delete();
//更新数据库,sda代表SqlDataAdapter对象
sda.Update(ds);
//更新DataSet对象中的数据
ds.Tables[0] .AcceptChanges();
在 Windows 应用程序中很多控件都提供了 DataSource 属性,并将 DataSet 或 DataTable 的值直接赋给该属性,这样在控件中即可显示从数据库中查询出来的数据。
常用的数据绑定控件有文本框(TextBox)、标签(Label)、列表框(ListBox)、组合框(ComboBox)、数据表格(DataGridView)等。
下面以组合框控件为例来讲解一下数据绑定的应用。
可视化数据绑定
组合框控件(ComboBox)在 Windows 窗体应用程序中是常用的控件,例如用于存放省市信息、专业、图书类型、房间类型等。
在 Windows 窗体应用程序中提供了可视化数据绑定和使用代码绑定数据的方法。
使用数据绑定的方式绑定组合框控件直接单击组合框的 “数据绑定快捷键” 图标,弹出“ComboBox任务”菜单,如下图所示。
ComboBox菜单
在其中选中“使用数据绑定项”复选框,显示“数据绑定模式”菜单,如下图所示。
数据绑定模式菜单
在该菜单中
“数据源”组合框用于选择要连接数据库中的数据表,相当于为控件设置 DataSource 属性;
“显示成员”组合框用于设置在组合框中显示的列名,可以通过组合框的Text属性获取;
“值成员”组合框用于设置组合框中的隐藏值,可以通过组合框的 Value 属性获取;
“选定值”组合框用于设置组合框中所选值使用的列名。
下面通过实例来演示组合框的绑定。
【实例 1】创建 Windows 窗体应用程序,设置显示专业信息的组合框,并将“显示成员”设置为专业名称列、将“值成员”设置为专业编号、将“选定值”设置为“计算机”。
根据题目要求,先创建专业信息表,建表语句如下。
create table major
(
id int primary key identity(1,1),
name varchar(20) unique
);
向该表中添加计算机、英语、自动化 3 个专业信息,通过“ComboEox任务”菜单设置数据绑定项,首先选择“数据源”组合框,并单击“添加项目数据源”链接,弹出如下图所示的对话框。
选择数据源类型对话框
选择“数据库”选项,单击“下一步”按钮,显示如下图所示的对话框。
选择数据库模型对话框
选择“数据集”选项,单击“下一步”按钮,显示如下图所示的对话框。
选择你的数据连接
在该界面中选择数据连接,如果没有建立数据连接,则需要新建连接。
单击“新建连接”按钮,弹出如下图所示的对话框。
选择数据源
其中列出了供用户选择的数据源,也可以添加其他的数据源,这里选择 Microsoft SQL Server 选项,单击“继续”按钮,弹出如下图所示的对话框。
添加连接
在其中输入服务器名,选择登录服务器的身份验证方式以及连接的数据库名或数据库文件信息,添加信息后的效果如下图所示。
添加连接
单击“测试连接”按钮,如果弹出“测试连接成功”提示,则数据库连接设置正确。
单击“确定”按钮,回到“选择你的数据连接”对话框,如下图所示。
选择你的数据连接
由于连接字符串存储一些敏感信息,在界面中提供了两个供用户选择的单选按钮,这里选择“是,在连接字符串中包含敏感数据”单选按钮,单击“下一步”按钮,显示如下图所示的对话框。
将连接字符串保存到应用程序配置文件中
在其中可以为连接字符串设置名称,也可以选择不保存连接串,保存后的连接字符串能在下一次建立数据库连接时使用。
选择数据库对象
在其中选择数据库对象,包括表、视图、存储过程、函数,可以选择一个对象,也可以选择多个对象,这里仅选择专业信息表(major),并设置数据集名称,如下图所示。
选择major表
单击“完成”按钮,即可完成对数据源的设置。
完成数据源的设置以后,分别设置“显示成员”“值成员”“选定值”组合框,设置后的效果如下图所示。
设置数据绑定模式后的效果
数据绑定后的运行效果
从上面的运行效果可以看出,在组合框中显示了专业信息表中的专业名称列的值。
使用代码绑定组合框
与数据绑定控件设置的属性类似,需要通过代码设置组合框的数据源、显示成员、值成员等内容。
具体设置的语句如下。
组合框对象.DataSource = DataTable 的对象
//设置组合框的显示成员属性
组合框对象.DisplayMember = 列名
//设置组合框的值成员属性
组合框对象.ValueMember = 列名
下面通过实例演示如何通过编写代码绑定组合框。
【实例 2】使用代码的方式绑定组合框显示专业名称,每次切换选项后弹出消息框显 示组合框中当前选择的值。
将上一实例中的数据绑定方式换成代码方式来绑定组合框显示专业名称,在窗体的加载事件中加入绑定组合框的代码,代码如下。
//窗体加载事件
private void ComboBoxForm_Load(object sender, EventArgs e)
{
//数据库连接串
string connStr = "Data Source=.;Initial Catalog=test;User ID=sa;Password=root";
//创建SqlConnection的实例
SqlConnection conn = null;
try
{
conn = new SqlConnection(connStr);
//打开数据库
conn.Open();
string sql = "select * from major";
//创建SqlDataAdapter类的对象
SqlDataAdapter sda = new SqlDataAdapter(sql, conn);
//创建DataSet类的对象
DataSet ds = new DataSet();
//使用SqlDataAdapter对象sda将查新结果填充到DataSet对象ds中
sda.Fill(ds);
//设置组合框的DataSource属性
comboBox1.DataSource = ds.Tables[0];
//设置组合框的DisPlayMember 属性
comboBox1.DisplayMember = "name";
//设置组合框的ValueMember属性
comboBox1.ValueMember = "id";
}
catch(Exception ex)
{
MessageBox.Show("出现错误!" + ex.Message);
}
finally
{
if (conn != null)
{
//关闭数据库连接
conn.Close();
}
}
}
运行该窗体,效果与上一实例相同。
在组合框的选项改变事件中将组合框中当前显示的内容显示到消息框中,代码如下。
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox1.Tag != null)
{
//获取组合框中显示的值
string name = comboBox1.Text;
//弹出消息框
MessageBox.Show("您选择的专业是:" + name);
}
}
组合框选项改变后弹出的消息框
在实际工作中,使用代码绑定的方式是应用最多的方式,一方面体现了代码的灵活性,另一个方面也增强了代码的可移植性。
数据表格控件是 WinForm 窗体应用程序中用于查询时以表格形式显示数据的重要控件,同样数据表格控件也可以使用可视化数据绑定和代码的方式来绑定数据表中的数据,并能在数据表格控件中实现对表中数据的修改和删除操作。
下面分别介绍使用可视化数据绑定方式绑定数据表格控件和使用代码方式绑定数据表格控件。
可视化方式绑定 DataGridView 控件
数据表格控件的可视化数据绑定也是通过控件的任务菜单完成的,如下图所示。
DataGridView任务菜单
在“DataGridView 任务”菜单中提供了“选择数据源”“编辑列”“添加列”,以及“启用添加”“启用编辑”“启用删除”“启用列重新排序”“在父容器中停靠”等选项。
其中:
选择数据源:与组合框控件中选择数据源的操作是相同的。
编辑列:用于在 DataGridView 控件中编辑列,包括添加列、给列设置别名等操作。
添加列:用于向 DataGridView 控件中添加列,并且可以在 DataGridView 控件中添加不同类型的控件用于显示新添加的列,例如添加一个按钮用于修改或删除表中的数据。
启用添加:允许用户向 DataGridView 控件中添加一行,相当于将 DataGridView 控件中的 AllowUserToAddRows 属性设置为 True。
启用编辑:允许用户编辑 DataGridView 控件中的值,相当于将 DataGridView 控件中的 Readonly 属性设置为 False。
启用删除:允许用户删除 DataGridView 控件中的值,相当于将 DataGridView 控件中的 AllowUserToDeleteRows 属性设置为 True。
启用列重新排序:允许启用手动列重新设置,相当于将 DataGridView 控件中的 AllowUserToOrderColumn 属性设置为 True。
在父容器中停靠:允许 DataGridView 控件在所在的窗体中最大化。
下面通过实例来演示以可视化的方法绑定 DataGridView 控件。
【实例 1】使用可视化绑定的方法将专业信息表中的专业编号和专业名称显示在 DataGridView 控件中,并为表中的列名设置别名。
根据题目要求,完成该实例需要以下步骤。
显示专业信息的窗体设计
2) 为窗体设置数据源
在上图所示的界面中单击 DataGridView 控件上的“按钮”按钮,在弹出的“DataGridView 任务”菜单中的选择数据源组合框中为 DataGridView 控件设置数据源。
选择数据源的方法与上一节《C# ComboBox》介绍的在组合框中选择数据源的方法是一样的,由于在前面的使用组合框的实例中已经为应用程序设置过数据源,所以这里 DataGridView 控件中的数据源直接选择已经设置好的数据源即可。
在选择数据源后,“DataGridView任务”菜单的效果如下图所示。
为DataGridView控件选择数据源
3) 编辑列
在上图所示的界面中单击“编辑列”,弹出如下图所示的对话框。
编辑列
在该对话框的左侧列出了专业信息表(major)中的所有列,右侧列出了列的属性,常用的属性如下表所示。
属性名称 | 说明 |
---|---|
Frozen | 设置用户在水平滚动 DataGridView 控件时列是否移动,默认是 False |
ColumnType | 设置显示列时的控件类型,默认是文本框 |
DataPropertyName | 设置绑定数据源中的列 |
HeaderName | 设置在 DataGridView 列中显示的列标题 |
Visible | 设置该列是否可见 |
在上图所示的对话框中将 id 列的列标题 (HeaderText) 属性设置为“编号”、将 name 列的列标题 (HeaderText) 属性设置为“专业名称”。
完成以上 3 个步骤后运行该窗体,效果如下图所示。
使用可视化数据绑定方式绑定DataGridView
从上面的运行效果可以看出,使用可视化数据绑定方式可以快速完成将数据表中的数据显示在 DataGridView 控件中的操作,并可以很容易地对绑定列的属性进行相关设置。
使用代码绑定 DataGridView 控件
使用代码绑定 DataGridView 控件时需要为该控件设置数据源 (DataSource) 属性,具 体的语句如下。
DataGridView 控件的名称.DataSource = DataTable 对象 ;
如果使用 DataSet 对象为 DataSource 属性赋值,则需要使用 DataSet 对象的 Tables 属性选择指定的数据表。
下面通过实例来演示如何使用代码绑定 DataGridView 控件。
【实例 2】使用代码的方式绑定 DataGridView 控件。
根据题目要求,在窗体的加载事件中加入代码绑定 DataGridView 控件,实现的代码如下。
//窗体加载事件
private void DataGridViewForm_Load(object sender, EventArgs e)
{
//数据库连接串
string connStr = "Data Source=.;Initial Catalog=test;User ID=sa;Password=root";
//创建SqlConnection的实例
SqlConnection conn = null;
try
{
conn = new SqlConnection(connStr);
//打开数据库
conn.Open();
string sql = "select * from major";
//创建SqlDataAdapter类的对象
SqlDataAdapter sda = new SqlDataAdapter(sql, conn);
//创建DataSet类的对象
DataSet ds = new DataSet();
//使用SqlDataAdapter对象sda将查新结果填充到DataSet对象ds中
sda.Fill(ds);
//设置表格控件的DataSource属性
dataGridView1.DataSource = ds.Tables[0];
}
catch (Exception ex)
{
MessageBox.Show("出现错误!" + ex.Message);
}
finally
{
if (conn != null)
{
//关闭数据库连接
conn.Close();
}
}
}
使用代码的方式绑定DataGridView控件
从上面的运行效果可以看出,通过设置 DataGridView 控件的 DataSource 属性即可绑定 DataGridView 控件,但绑定后的 DataGridView 控件中的标题是数据表中的列名。
如果需要更改 DataGridView 控件的列标题,则需要在上面的代码中加入以下代码。
//设置第 1 列的列标题
dataGridView1.Columns[0] .HeaderText="编号";
//设置第2列的列标题
dataGridView1. Columns[1].HeaderText="专业名称";
接下来我们通过一个完整的实例来实现课程信息管理功能的操作,包括查询、修改、删除课程信息的操作。
为了简化实例,添加课程信息的操作直接在 SQL Server 数据库中完成。
下面分几个步骤完成。
use test;
create table course
(
id int primary key identity(1,1),
name varchar(20),
credit numeric(3,1),
remark varchar(50)
);
向表中添加数据的语句如下。
insert into course (name, credit, remark) values ('计算机基石 ' , 2, '无');
insert into course (name, credit, remark) values ('C# 程序开发', 2.5 , '机房授课');
insert into course (name, credit, remark) values ('数据库原理',1,'无');
insert into course (name, credit, remark) values ('体育',1,'无');
insert into course (name, credit, remark) values ('职业素养培训',0.5,'无');
在 SQL Server 中执行上述 SQL 语句即可完成课程信息表(course)的创建和数据的添加。
2) 课程信息管理界面的设计
在课程信息管理界面中提供了 DataGridView 控件用于显示课程信息,并提供了根据课程名称查找课程信息、修改以及删除的功能。
课程信息管理界面设计
3) 在加载窗体时显示所有课程信息
本例中使用编写代码的方式实现 DataGridView 控件的数据绑定,并在窗体的加载事件中加入数据绑定的代码。
由于查询所有课程信息的代码将在后面的修改和删除功能中重复使用,所以单独定义一个方法来实现查询所有课程信息。代码如下。
//窗体加载事件
private void DataGridViewForm_Load(object sender, EventArgs e)
{
//调用查询全部课程的方法
QueryAllCourse();
}
//查询全部课程
private void QueryAllCourse()
{
//数据库连接串
string connStr = "Data Source=.;Initial Catalog=test;User ID=sa;Password=root";
//创建SqlConnection的实例
SqlConnection conn = null;
try
{
conn = new SqlConnection(connStr);
//打开数据库
conn.Open();
string sql = "select * from course";
//创建SqlDataAdapter类的对象
SqlDataAdapter sda = new SqlDataAdapter(sql, conn);
//创建DataSet类的对象
DataSet ds = new DataSet();
//使用SqlDataAdapter对象sda将查新结果填充到DataSet对象ds中
sda.Fill(ds);
//设置表格控件的DataSource属性
dataGridView1.DataSource = ds.Tables[0];
//设置数据表格上显示的列标题
dataGridView1.Columns[0].HeaderText = "编号";
dataGridView1.Columns[1].HeaderText = "课程名称";
dataGridView1.Columns[2].HeaderText = "学分";
dataGridView1.Columns[3].HeaderText = "备注";
//设置数据表格为只读
dataGridView1.ReadOnly = true;
//不允许添加行
dataGridView1.AllowUserToAddRows = false;
//背景为白色
dataGridView1.BackgroundColor = Color.White;
//只允许选中单行
dataGridView1.MultiSelect = false;
//整行选中
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
}
catch (Exception ex)
{
MessageBox.Show("查询错误!" + ex.Message);
}
finally
{
if (conn != null)
{
//关闭数据库连接
conn.Close();
}
}
}
查询全部课程信息
4) 完成课程名称的模糊查询
在“查询”按钮的单击事件中加入根据课程名称模糊查询的代码,具体如下。
//查询按钮单击事件
private void button1_Click(object sender, EventArgs e)
{
if (textBox1.Text != "")
{
//数据库连接串
string connStr = "Data Source=.;Initial Catalog=test;User ID=sa;Password=root";
//创建SqlConnection的实例
SqlConnection conn = null;
try
{
conn = new SqlConnection(connStr);
//打开数据库
conn.Open();
string sql = "select * from course where name like '%{0}%'";
//填充占位符
sql = string.Format(sql, textBox1.Text);
//创建SqlDataAdapter类的对象
SqlDataAdapter sda = new SqlDataAdapter(sql, conn);
//创建DataSet类的对象
DataSet ds = new DataSet();
//使用SqlDataAdapter对象sda将查新结果填充到DataSet对象ds中
sda.Fill(ds);
//设置表格控件的DataSource属性
dataGridView1.DataSource = ds.Tables[0];
}
catch (Exception ex)
{
MessageBox.Show("出现错误!" + ex.Message);
}
finally
{
if (conn != null)
{
//关闭数据库连接
conn.Close();
}
}
}
}
课程名称模糊查询功能
从上面的运行效果可以看出,在文本框中输入“计算机”,则可以实现查询所有课程 名称中含有“计算机”字样的课程信息。
5) 实现修改功能
在 DataGridView 控件中选中一条课程信息,单击“修改”按钮,弹出修改课程信息界面并在该界面中显示要修改的信息,修改界面的设计如下图所示。
修改课程信息界面
选中 DataGridView 控件的一条课程信息,单击“修改”按钮。
“修改”按钮的单击事件中的代码如下。
//修改课程信息
private void button2_Click(object sender, EventArgs e)
{
//获取DataGridView控件中的值
//获取课程编号
string id = dataGridView1.SelectedRows[0].Cells[0].Value.ToString();
//获取课程名称
string name = dataGridView1.SelectedRows[0].Cells[1].Value.ToString();
//获取课程名称
string credit = dataGridView1.SelectedRows[0].Cells[2].Value.ToString();
//获取课程名称
string remark = dataGridView1.SelectedRows[0].Cells[3].Value.ToString();
//创建updateForm类的对象,并将课程信息传递给修改界面
updateForm updateform = new updateForm(id, name, credit, remark);
//弹出修改信息窗口
DialogResult dr = updateForm.ShowDialog();
//判断是否单击确定按钮
if (dr == DialogResult.OK)
{
//调用查询全部课程方法
QueryAllCourse();
}
}
修改界面 (UpdateForm) 中的代码如下。
//带参数的构造方法
public updateForm(string id,string name,string credit,string remark)
{
InitializeComponent();
textBox1.Text = id;
textBox2.Text = name;
textBox3.Text = credit;
textBox4.Text = remark;
}
//确认按钮单击事件
private void button1_Click(object sender, EventArgs e)
{
//数据库连接串
string connStr = "Data Source=.;Initial Catalog=test;User ID=sa;Password=root";
//创建SqlConnection的实例
SqlConnection conn = null;
try
{
conn = new SqlConnection(connStr);
//打开数据库
conn.Open();
string sql = "update course set name='{0}',credit='{1}',remark='{2}' where id='{3}'";
//填充占位符
sql = string.Format(sql, textBox2.Text, textBox3.Text, textBox4.Text, textBox1.Text);
//创建SqlCommand类的对象
SqlCommand cmd = new SqlCommand(sql, conn);
//执行修改操作的SQL
cmd.ExecuteNonQuery();
//弹出成功提示
MessageBox.Show("修改成功!");
//设置当前窗体DislogResult结果为OK
this.DialogResult = DialogResult.OK;
//关闭窗体
this.Close();
}
catch (Exception ex)
{
MessageBox.Show("修改失败!" + ex.Message);
}
finally
{
if (conn != null)
{
//关闭数据库连接
conn.Close();
}
}
}
//取消按钮单击事件
private void button2_Click(object sender, EventArgs e)
{
//关闭窗体
this.Close();
}
修改功能运行效果
6) 实现删除功能
为“删除”按钮添加单击事件,将选中的课程信息删除并刷新界面中查询出来的数据。实现的代码如下。
//删除按钮的单击事件
private void button3_Click(object sender, EventArgs e)
{
//获取DataGridView控件中选中行的编号列的值
int id = int.Parse(dataGridView1.SelectedRows[0].Cells[0].Value.ToString());
//数据库连接串
string connStr = "Data Source=.;Initial Catalog=test;User ID=sa;Password=root";
//创建SqlConnection的实例
SqlConnection conn = null;
try
{
conn = new SqlConnection(connStr);
//打开数据库
conn.Open();
string sql = "delect from course where id='{0}'";
//填充占位符
sql = string.Format(sql, id);
//创建SqlCommand类的对象
SqlCommand cmd = new SqlCommand(sql, conn);
//执行SQL语句
cmd.ExecuteNonQuery();
//弹出消息提示删除成功
MessageBox.Show("删除成功!");
//调用查询全部的方法,刷新DataGridView控件中的数据
QueryAllCourse();
}
catch (Exception ex)
{
MessageBox.Show("删除失败!" + ex.Message);
}
finally
{
if (conn != null)
{
//关闭数据库连接
conn.Close();
}
}
}
删除操作运行效果
单击删除消息框中的“确定”按钮,’即可刷新 DataGridView 控件中的数据。