概述
上一节《C#+ADO.NET连接MSSQL Server数据库》,我们使用ADO.NET实现了基础的C#应用程序与SQL Server数据库连接功能。但这只是C#应用程序与SQL Server数据交互的开端。
连接数据库的目的当然是要对数据库、数据表的结构或者数据进行操作,如:创建数据库,创建/修改表结构,向数据表中写入数据,更新数据,查询数据甚至删除数据等等。
本节,我们将学习在C#应用程序中使用ADO.NET从SQL Server数据库中查询数据并在.NET 5的控制台应用程序中显示。
准备工作
在本节教程开始之前,先准备一张数据表并在其中填充测试用的数据。你可以在 Datum 这个数据生成网站生成模拟数据。
以下是笔者准备的SQL Server数据库的表结构脚本如下:
CREATE TABLE Customer (
Id INT IDENTITY(1,1) PRIMARY KEY,
FamilyName NVARCHAR(50),
GivenName NVARCHAR(50),
Email NVARCHAR(50),
Gender NVARCHAR(10),
IpAddress NVARCHAR(20),
CreatedAt DATETIME
);
请点击这里获取完整示例脚本 —> C#+ADO.NET读取MSSQL Server数据库中的数据(示例SQL脚本)。
通过DataReader检索数据
要使用DataReader
检索数据,首先需要创建Command
对象的实例,然后通过调用Command.ExecuteReader()
方法以创建DataReader
并从数据源获取数据。当检索大量数据时,因为数据不会缓存在内存中,DataReader
是一个很好的选择。
以下是使用Command
创建DataReader
并从数据源检索数据的示例,代码如下:
using System;
using System.Data.SqlClient;
namespace ConsoleApp1
{
class Program
{
// 定义一个私有字段,存储数据库连接字符串信息(这里连接的是mssqllocaldb数据库,登录方式为Windows身份验证)
private const string _connectionString = "Server=(localdb)\\mssqllocaldb;Integrated Security=true;Database=Demo";
static void Main(string[] args)
{
// 1.实例化一个SQL Server的连接对象(这里使用using语句块,以自动释放连接资源)
using SqlConnection connection = new SqlConnection(_connectionString);
// 2.实例化一个SqlCommand对象(command),构造函数参数分别为SQL查询语句和SqlConnection数据库连接对象
var command = new SqlCommand("SELECT TOP 100 Id,FamilyName,GivenName,Email,Gender,IpAddress,CreatedAt FROM Customer", connection);
// 3.打开数据库连接
connection.Open();
// 4.调用command.ExecuteReader()创建SqlDataReader对象并检索数据
using SqlDataReader reader = command.ExecuteReader();
// 5.检查reader对象中是否有数据源返回的数据行
if (reader.HasRows)
{
// 6.使用while依次读取reader对象中的每一行数据,直到读取完最后一行
while (reader.Read())
{
// 7.取数据行中的列,并将其打印到控制台
Console.Write($"Id:{reader["Id"]}");
Console.Write($"\t姓名:{reader["FamilyName"]}{reader["GivenName"]}");
Console.Write($"\t邮箱:{reader["Email"],-30}");
Console.Write($"\t性别:{reader["Gender"]}");
Console.Write($"\tIP地址:{reader["IpAddress"],-15}");
Console.Write($"\t创建时间:{reader["CreatedAt"],-15}");
// 换行
Console.WriteLine();
}
}
Console.ReadKey();
}
}
}
示例代码中的:
\t
:制表符, {reader[“Email”],-30}:左对齐,如果少于30个字符,则用空格补齐
运行结果如下图:
读取DataReader
行中的列元素有两种方式,一种是上面示例的reader["列名"]
,另一种是通过列的索引方式,如:GetDateTime, GetDouble, GetGuid, GetInt32等等方法,如图:
其中:reader["列名"]
方式只需要指定正确的列名即可,得到的数据类型是object,而第二种调用Get方法需要知道数据源的原始数据类型,并且还要指定列的索引位置,而得到的是显式的数据类型,如图示:
注: DataReader没有直接返回数据行数的属性或方法。也就是说,你不能通过DataReader的实例直接得到当前实例中的总数据行数,想要得到当前DataReader实例的数据行数,需要自己实现(一种方案为:在循环中累加计数)。
特别注意: 在使用完后,请调用reader.Close()
方法关闭DataReader(本示例中使用了using
语句,会自动释放)。
通过DataSet检索数据
ADO.NET除了可以使用DataReader
检索数据外,还有DataSet
可以返回数据,且结果是一个数据集。
正如前面小节《ADO.NET五大核心对象》中介绍的,DataSet
(数据集)是ADO.NET的核心。DataSet
本质上是DataTable
对象的集合。每个对象依次包含一个DataColumn
和DataRow
对象的集合。数据集还包含一个关系集合,可用于定义数据表对象之间的关系。
DataSet是驻留于内存中的数据集,可以看做是内存中的数据库,内部用XML来描述数据。而数据集(DataSet
)与数据源之间检索和保存数据则是通过DataAdapter
这个数据适配器来完成的。
以下演示使用ADO.NET从SQL Server数据库中检索指定数据表并输出到.NET 5控制台应用程序,示例代码如下:
using System;
using System.Data;
using System.Data.SqlClient;
namespace ConsoleApp1
{
class Program
{
// 定义一个私有字段,存储数据库连接字符串信息(这里连接的是mssqllocaldb数据库,登录方式为Windows身份验证)
private const string _connectionString = "Server=(localdb)\\mssqllocaldb;Integrated Security=true;Database=Demo";
static void Main(string[] args)
{
// 1.实例化一个SQL Server的连接对象(这里使用using语句块,以自动释放连接资源)
using SqlConnection connection = new SqlConnection(_connectionString);
// 2.实例化一个SqlDataAdapter数据适配器对象(adapter),构造函数参数分别为SQL查询语句和SqlConnection数据库连接对象
SqlDataAdapter adapter = new SqlDataAdapter("SELECT TOP 100 Id,FamilyName,GivenName,Email,Gender,IpAddress,CreatedAt FROM Customer", connection);
// 3.创建一个DataSet实例,DataSet位于命名空间System.Data,请注意引入
DataSet ds = new DataSet();
// 通过DataAdapter,有以下三种方式获取到数据表DataTable
// 方式一
// 4.调用Fill方法将数据填充到数据集对象ds中,如果指定数据库连接未打开,Fill方法会隐式打开数据库连接
adapter.Fill(ds);
// 5.从数据集对象ds中取出第一个(下标为0)数据表,设置其变量名为table
DataTable table = ds.Tables[0];
// 方式二
// Fill方法还有重载方法,第二个参数表示目标表的表名,如下:
// adapter.Fill(ds,"customer");
// 通过目标表的表名获取DataTable数据表
// DataTable customer = ds.Tables["customer"];
// 方式三
// Fill方法的另一个重载方法,参数为一个DataTable实例对象,如下:
// adapter.Fill(table);
// 6.得到数据表table中的所有数据行集合,设置其变量名为rows
DataRowCollection rows = table.Rows;
// 7.打印出当前数据行集合中所有的数据总行数
Console.WriteLine($"总行数:{rows.Count}");
// 8.循环遍历数据行集合的每一行
for (int i = 0; i < rows.Count; i++)
{
// 9.循环中的当前行
var row = rows[i];
// 10.通过列名读取当前行指定列的值,并打印到控制台
Console.Write($"Id:{row["Id"]}");
Console.Write($"\t姓名:{row["FamilyName"]}{row["GivenName"]}");
Console.Write($"\t邮箱:{row["Email"],-30}");
Console.Write($"\t性别:{row["Gender"]}");
Console.Write($"\tIP地址:{row["IpAddress"],-15}");
Console.Write($"\t创建时间:{row["CreatedAt"],-15}");
Console.WriteLine();
}
// 通常需调用connection.Close();方法关闭数据库连接
// 但上面使用了using关键字,所以此处无需手动关闭(connection作用域结束时,会自动释放connection资源)
Console.ReadKey();
}
}
}
运行结果如下图:
发表评论
登录用户才能发表评论, 请 登 录 或者 注册