ASP.NET ADO.NET SQL Server 数据库访问

ASP.NET 专栏收录该内容
5 篇文章 0 订阅

目录

1、ADO.NET 基础

1.1、ADO.NET 中的常用对象

ADO.NET 的常用对象如下:

  1. Connection 对象:连接对象,提供与数据库的连接。
  2. Command 对象:命令对象,表示要执行的数据库命令。
  3. Parameter 对象:参数对象,表示数据库命令中标记代替的参数。
  4. DataReader 对象:数据流对象,表示从数据源中提供的快速的,只向前的,只读的数据流。
  5. DataAdapter 对象:数据适配器对象,提供连接 DataSet 对象和数据源的桥梁。 DataAdapter 使用 Command 对象在数据源中执行 SQL 命令,以便将数据加载到 DataSet 中,并保证 DataSet 中数据的更改与数据源一致。
  6. DataSet 对象:数据集对象,表示命令的结果数据集。DataSet 是包含一个或多个 DataTable 对象的集合,这些对象由数据行,数据列以及主键,外键,约束数据的关系信息组成。

1.2、ADO.NET 数据库操作过程

使用 ADO.NET 访问数据库的规范步骤如下:

  1. 创建一个连接对象。
  2. 使用对象的 Open() 方法打开连接。
  3. 创建一个封装 SQL 命令的对象。
  4. 调用执行命令的对象。
  5. 执行数据库操作。
  6. 执行完毕,释放连接。

2、SqlConnection 对象

2.1、SqlConnection 对象的属性与方法

在 ASP.NET 开发中,连接 SQL Server 数据库需要使用 SqlConnection(连接)对象,对应的类包含在System.Data.SqlClient 命名空间中,使用该类首先需要添加命名空间的引用。

using System.Data.SqlClient;

2.1.1、SqlConnection 类的主要属性

属性名说明
ConnectionString获取或设置用于打开 SQL Server 数据库的字符串
ConnectionTimeout获取终止尝试并生成错误之前在尝试建立连接时所等待的时间
Database获取当前数据库的名称或打开连接后要使用的数据库名称
DataSource获取要连接的 SQL Server 的实例名称
State获取最近连接操作时 SqlConnection 的状态
ServerVersion获取客户端所连接到的 SQL Server 的实例版本

说明:
State属性具有如下枚举值:

  • Broken:数据连接中断,只有连接曾经打开过才会出现此状态。
  • Open:连接处于打开状态。
  • Connecting:连接对象处于正在与数据源连接状态。
  • Executing:连接对象处于正在执行命令状态。
  • Fetching:连接对象处于正在检索数据状态。
  • Closed:连接对象处于关闭状态。

2.1.2、SqlConnection 类的主要方法

方法名说明
Close()关闭与数据库之间的连接。此方法是关闭任何打开连接的首选方法
Dispose()释放使用的所有资源
Open()打开数据库连接

2.1.3、SqlConnection 类的构造函数

构造函数说明
SqlConnection()初始化 SqlConnection 类的新实例
SqlConnection(String)针对参数中的连接字符串,初始化 SqlConnection 类的新实例

2.2、创建连接字符串

在连接数据库前,需要为连接设置连接字符串(ConnectionString),连接字符串将告知应用程序在什么位置找数据库管理系统,使用何种方式登录数据库系统,与哪个数据库进行连接,从而正确地与 SQL Server 数据库建立连接。连接字符串实例代码如下:

server='服务器地址';database='数据库名称';uid='数据库用户名';pwd='数据库密码';

上述代码是数据库连接字符串的基本格式。其中 server 是 SQL Server 服务器的地址,如果数据库服务器相对于应用程序是本地服务器,则只需要配置为 (local)/sqlexpress 或者 ./sqlexpress 即可,而如果是远程服务器,则需要填写具体的IP地址。uid 是数据库登录时的用户名,pwd 是数据库登录时使用的密码。此外,数据库服务器也可以使用 Windows 身份验证,对应的属性设置为 trusted_connection=true,这种连接方式有助于在连接到 SQL Server 时提供安全保护,因为它不会在连接字符串中公开用户 ID 和密码,是安全级别要求较高时推荐的数据库连接方法。

2.2.1、ConnectionString 对象的属性

属性名说明
Server 或 Data Source访问的 SQL Server 服务器的地址
Database 或 Initial Catalog访问的数据库名
Uid 或 User Id数据库登录时的用户名
Pwd 或 Password数据库登录时使用的密码
trusted_connection 或 Integrated Security属性值赋值为 true,表示使用信任模式即 Windows 身份认证登录数据库

说明:

  1. 连接字符串"server=‘服务器地址’;database=‘数据库名称’;uid=‘数据库用户名’;pwd=‘数据库密码’“中的单引号可以缺省,等价于"server=服务器地址;database=数据库名称;uid=数据库用户名;pwd=数据库密码”。
  2. 连接字符串中所有的属性值对应为数据库中的 SQL 语句,不区分大小写。

2.3、Web.config 文件中的连接字符串

对于应用程序而言,可能需要在多个页面的程序代码中使用连接字符串来连接数据库。当数据库发生改变时,要修改所有的连接字符串。可以在 配置字节中定义应用程序的数据库连接字符串,所有的程序从该配置字节读取字符串,当需要改变连接时,只需要在配置字节中重新设置即可。

2.3.1、在 Web.config 文件中配置数据库连接字符串

在 Web.config 文件中添加如下代码,即可以将应用程序的数据库连接字符串存储在 配置字节中。

<connectionStrings>
    <add name="ConnectionName" connectionString="Server=. \ SQLEXPRESS;Database=demo;Uid=sa;Pwd=abc123;providerName="System.Data.SqlClient"/>
</connectionStrings>

2.3.2、获取 Web.config 文件中数据库连接字符串

在页面的.cs内通过一段代码获取 标签里的数据库连接的字符串,代码如下:

引用命名空间:

using System.Configuration;

定义变量并赋值:

string conStr = ConfigurationManager.ConnectionStrings["ConnectionName"].ToString();

conStr 变量值即为 Web.config 文件中保存的连接字符串。

3、SqlCommand 对象

3.1、SqlCommand 对象的属性与方法

SqlCommand(命令)对象可以使用数据命令直接与数据源进行通信。当需要向数据库内插入一条数据,或者删除数据库中的某条数据时,就需要使用到 SqlCommand 对象,对应的类包含在 System.Data.SqlClient 命名空间中。SqlCommand 类包括了数据库中执行命令时的所有必要信息,当 SqlCommand 对象的属性设置好之后,就可以调用 SqlCommand 对象的方法对数据库中的数据进行处理。

3.1.1、SqlCommand 类的主要属性

属性名说明
Name获取或设置 Command 对象的名称
Connection获取或设置对 Connection 对象的引用
CommandType获取或设置命令类型为 SQL 语句或存储过程,默认情况下是 SQL 语句
CommandText获取或设置命令对象包含的 SQL 语句或存储过程名
Parameters命令对象的参数集合

说明:
(1)CommandType 属性具有如下三种枚举值:

  • Text:表示 Command 对象用于执行 SQL 语句,该属性的默认值为 Text。
  • StoredProcedure:表示 Command 对象用于执行存储过程。
  • TableDirect:表示 Command 对象用于直接处理某张表。

(2)CommandText 属性根据 CommandType 属性的取值来决定所表示的意义,分为下列三种情况:

  • 如果 CommandType 属性取值为 Text,则 CommandText 属性为 SQL 语句的内容。
  • 如果 CommandType 属性取值为 StoredProcedure,则 CommandText 属性为存储过程的名称。
  • 如果 CommandType 属性取值为 TableDirect,则 CommandText 属性为表的名称。

3.1.2、SqlCommand 对象的主要方法

方法名说明
ExecuteReader()执行查询操作,返回一个具有多行多列数据的数据流
ExecuteScalar()执行查询操作,返回单个值
ExecuteNonQuery()执行插入,修改或删除操作,返回本次操作受影响的行数

3.1.3、SqlCommand 对象的构造函数

构造函数说明
SqlCommand()初始化 SqlCommand 类的新实例
SqlCommand(cmdText)初始化包含命令文本的命令对象,cmdText 为命令文本
SqlCommand(cmdText,connection)初始化包含命令文本和连接对象的命令对象,cmdText 为命令文本,connection 为连接对象

3.2、SqlParameter 参数对象

使用 SqlCommand 对象执行 SQL 语句和存储过程时,在 SQL 语句和存储过程中往往带有很多参数,为了正确指定参数的值,可以使用 SqlParameter 对象方便地设置 SQL 语句和存储过程的参数。

3.2.1、SqlParameter 对象的主要属性

属性名说明
ParameterName获取或设置参数的名称
SqlDbType获取或设置指定参数的数据类型,如整形,字符型等
Direction获取或设置指定参数的方向
Value获取或设置指定输入参数的值

说明:
Direction 属性具有如下枚举值:

  • ParameterDirection.Input:指明为输入参数,Direction 属性的默认值。
  • ParameterDirection.Output:指明为输出参数。
  • ParameterDirection.InputOutput:指明为输入和输出参数。
  • ParameterDirection.ReturnValue:指明为返回值。

使用 SqlCommand 对象执行带参数的 SQL 语句时可以创建一个 SqlParameter 对象,直接添加到 SqlCommand 对象的参数集合中来指定 SQL 语句中所带参数的值。

4、SqlDataReader 对象

4.1、SqlDataReader 对象的属性与方法

SqlDataReader(数据访问)对象可以从数据库中得到只读,向前的数据流,对应的类包含在 System.Data.SqlClient 命名空间中。每次的访问或操作只有一个记录保存在服务器的内存中,SqlDataReader 具有较快的访问能力,占用较少的服务器资源。

4.1.1、SqlDataReader 对象的主要属性

属性名说明
FieldCount获取当前行中的列数
IsClosed获取一个布尔值,指示 SqlDataReader 对象是否关闭
RecordAffect获取执行 SQL 语句时修改的行数

4.1.2、SqlDataReader 对象的主要方法

方法名说明
Read()获取当前行中的列数
Close()关闭 SqlDataReader 对象
IsDBNull返回布尔值,表示列是否包含 NULL 值
GetName()返回索引为 i 的字段的字段名
GetBoolean()获取指定列的值,类型为布尔值
GetString()获取指定列的值,类型为字符串
GetByte()获取指定列的值,类型为字节
GetInt32()获取指定列的值,类型为整型值
GetDouble()获取指定列的值,类型为双精度值
GetDateTime()获取指定列的值,类型为日期时间值
GetValue()获取索引为 i 指定列的值,类型为对象

SqlDataReader 类没有构造函数,如果要创建 SqlDataReader 类的对象,只可以通过 SqlCommand 类的 ExecuteReader() 方法得到一个 SqlDataReader 对象。

4.2、使用 SqlDataReader 对象读取数据

SqlDataReader 对象的 Read() 方法可以判断 SqlDataReader 对象中的数据是否还有下一行,并将游标下移到下一行。通过 Read() 方法可以判断 SqlDataReader 对象中的数据是否读完。示例代码如下:

while(dr.Read())

同样,通过 Read() 方法也可以遍历读取数据库中行的信息。在读取到一行时,获取某列的值只需要使用索引器,即“[”和“]”运算符来确定某一列的值,示例代码如下:

while(dr.Read())
{
	Response.Write(dr["sname"].ToString()+"<hr/>");
}

上述代码通过 dr[“sname”] 获取数据库中 sname 这一列的值。同样,也可以通过索引获取某一列的值,示例代码如下:

while(dr.Read())
{
Response.Write(dr[1].ToString()+"<hr/>");
}

在 SqlDataReader 对象没有关闭之前,数据库连接会一直保持 Open 状态,并且一个连接只能被一个 SqlDataReader 对象使用,所以在使用 SqlDataReader 时,使用完毕应该立即调用 SqlDataReader.Close() 将其关闭。

5、DataSet 对象

DataSet(数据集)是 ADO.NET 中用来访问数据库的特定对象,对应的类包含在 System.Data 命名空间中。可以用来存储从数据库查询到的数据结果,在获得数据或更新数据后立即与数据库断开,可以高效地访问和操作数据库。可以简单地把 DataSet 想象成虚拟的表,但是这个表不是简单的只存数据,而是一个具有数据结构的表,并且这个表是存放在内存中的。
由于 DataSet 对象具有离线访问数据库的特性,所以它更能用来接收海量的数据信息。DataSet 对象本身不同数据库发生关系,而是通过 DataAdapter 对象从数据库中获取数据并把修改后的数据更新到数据库。

5.1、DataSet 对象

DataSet 对象能够支持多表,表间关系,数据库约束等,可以用来模拟简单的数据库模型。

5.1.1、DataSet 对象的主要属性

属性名说明
CaseSensitive获取或设置表中的字符串比较是否区分大小写,如果区分大小写则为 false,默认值为 false
DataSetName获取或设置当前 DataSet 对象名
Tables获取包含在 DataSet 对象中的表的集合
Relations获取用于数据集中表的关系集合
Namespace获取或设置命名空间 DataSet

5.1.2、DataSet 对象的主要方法

方法名说明
AcceptChanges()提交 DataSet 自加载以来或自上次调用 AcceptChanges 以来所做的所有更改
Clear()清除 DataSet 的所有表中的数据
Copy()复制 DataSet 的结构和数据
Dispose()释放所有资源
GetChanges()获取 DataSet 自加载后上一次更改的内容
Merge()合并指定 DataSet 到当前 DataSet
Reset()从 DataSet 中清除所有表

5.1.3、DataSet 对象的构造函数

构造函数说明
DataSet()初始化 DataSet 类的新实例
DataSet(string)初始化具有给定名称的 DataSet 类

5.2、DataTable 对象

DataSet 的 Tables 属性表示一个表的集合,每一个表都是一个 DataTable(数据表)对象。应用中每个 DataTable 对象可以表示数据库中的一张表或者多表查询得到的一个结果,可以通过 Tables 集合的索引器访问每张表,索引器的参数可以是字符串类型的表名,也可以是索引值。

5.2.1、Tables 集合的属性和方法

5.2.1.1、Tables 集合的主要属性
属性名说明
Counts获取 Tables 集合中表的个数
5.2.1.2、Tables 集合的主要方法
方法名说明
Add()向 Tables 集合中添加一张表
AddRange()向 Rows 集合添加一个表的数组
Clear()移除 Tables 集合中所有的表
Contains()判断指定表是否在 Tables 集合中
Insert()向 Tables 集合的指定位置插入一张表
IndexOf()检索指定表在 Tables 集合中的索引
Remove()从 Tables 集合中移除指定的表
RemoveAt()从 Tables 集合中移除指定索引位置的表

5.2.2、DataTable 对象

DataTable 表示一个内存中关系数据的表,可以简单地将 DataTable 想象成一个表。DataTable 也是 DataSet 中最常用的对象,可以独立创建和使用,也可以由其他 .NET Framework 对象使用。
表中的集合形成了二维表的数据结构,具有 Rows 集合和 Columns 集合等属性。

5.2.2.1、DataTable 对象的主要属性
属性名说明
CaseSensitive获取表中的字符串比较时是否区分大小写
Columns获取列的集合
Constraints获取约束的集合
DataSet获取表所属的 DataSet
HasErrors获取表中的错误信息
MinimumCapacity获取或设置此表的初始大小
PrimaryKey获取或设置数据表的主码
TableName获取或设置 DataTable 的名称
Rows获取行的集合
5.2.2.2、DataTable 对象的主要方法
方法名说明
AcceptChanges()提交自上次调用 AcceptChanges 后表的所有更改
Clear()清除 DataTable 中的所有数据
Copy()复制 DataTable 的结构和数据
GetChanges()获取 DataTable 加载后的所有更改和调用
GetErrors()获取 DataRow 对象包含的错误数组
Merge()合并指定 DataTable 到当前 DataTable
NewRow()创建一个相同架构的 DataRow
Reset()重置 DataTable 到其原始状态。重置中删除所有数据,索引,关系和表的列。如果数据集包含一个数据表,该表重置之后仍为数据集的一部分
5.2.2.3、DataTable 对象的构造函数
构造函数说明
DataTable()初始化 DataTable 类的新实例
DataTable(string)初始化具有给定名称的 DataTable 类

5.3、DataColumn 对象

DataTable 的 Columns 属性表示表的列集合,每个列都是一个 DataColumn(数据列)对象。应用中每个 DataColumn 对象可以表示数据库中的一个字段或者由聚合函数等得到的一个新属性,可以通过 Columns 集合的索引器访问表中的每一列,索引器的参数可以为字符串类型的列名,也可以是索引值。

5.3.1、Columns 集合的属性和方法

5.3.1.1、Columns 集合的主要属性
属性名说明
Counts获取 Columns 集合中列的个数
5.3.1.2、Columns 集合的主要方法
方法名说明
Add()向 Columns 集合中添加一列
AddRange()向 Columns 集合中添加一个列的数组
Clear()移除 Columns 集合中所有的列
Contains()判断指定列是否在 Columns 集合中
Insert()向 Columns 集合的指定位置插入一列
IndexOf()获取指定列在 Columns 集合中的索引
Remove()从 Columns 集合中移除指定的列
RemoveAt()从 Columns 集合中移除指定索引位置的列

5.3.2、DataColumn 对象

DataColumn 是用来模拟物理数据库中的列,多个 DataColumn 组成了 DataTable 中列的架构。

5.3.2.1、DataColumn 对象的主要属性
属性名说明
AllowDBNull获取或设置是否可以为空值
AutoIncrement获取或设置是否允许以自动递增的形式添加值
Caption获取或设置列标题
ColumnName获取或设置列的名称 DataCloumnCollection
DefaultValue获取或设置列的默认值
MaxLength获取或设置文本列的最大长度
ReadOnly获取或设置列是否为只读
Table获取 DataTable 列是否属于表
5.3.2.2、DataColumn 对象的主要方法
方法名说明
Dispose()释放使用的所有资源
5.3.2.3、DataColumn 对象的构造函数
构造函数说明
DataColumn()初始化 DataColumn 类的对象
DataColumn(string)初始化指定名称的 DataColumn 类

5.4、DataRow 对象

DataTable 的 Rows 属性表示表的行集合,每个行都是一个 DataRow(数据行)对象,应用中每个 DataRow 对象可以表示数据库中的一条记录或者是多表查询得到的一条数据,使用中可以通过 Rows 集合的索引器访问表中的每一行,索引器的参数是行的索引值。

5.4.1、Rows 集合的属性与方法

5.4.1.1、Rows 集合的主要属性
属性名说明
Counts获取 Rows 集合中行的个数
5.4.1.2、Rows 集合的主要方法
方法名说明
Add()向 Rows 集合中添加一行
AddRange()向 Rows 集合中添加一个行的数组
Clear()移除 Rows 集合中所有的行
Contains()判断指定行是否在 Rows 集合中
Insert()向 Rows 集合的指定位置插入一行
IndexOf()获取指定行在 Rows 集合中的索引
Remove()从 Rows 集合中移除指定的行
RemoveAt()从 Rows 集合中移除指定索引位置的行

5.4.2、DataRow 对象

在创建了表和表中列的集合,并使用约束定义表的结构后,可以使用 DataRow 对象向表中添加新的数据行,这一操作同数据库中 insert 语句类似。插入一个新行,首先要声明一个 DataRow 类型的变量,DataRow 对象没有构造函数,只能使用 DataTable 对象的 NewRow() 方法返回一个新的 DataRow 对象。
DataTable 会根据 DataCloumnCollection 定义的表结构来创建 DataRow 对象。

5.4.2.1、DataRow 对象的主要属性
属性名说明
CaseSensitive获取表中的字符串比较时是否区分大小写
Columns获取表的列集合
Constraints获取表的约束集合
DataSet获取表所属的DataSet
HasErrors获取某一错误信息是否属于该行
MinimumCapacity获取或设置此表的初始大小
PrimaryKey获取或设置数据表的主键列数组
TableName获取或设置 DataTable 的名称
Rows获取属于此表的行的集合
5.4.2.2、DataRow 对象的主要方法
方法名说明
AcceptChanges()提交自上次调用 AcceptChanges 以来对此表所做的所有更改
Clear()清除 DataTable 的所有数据
Copy()复制 DataTable 的结构和数据
GetChanges()获取自上次调用 AcceptChanges 以来对此类所做的更改
GetErrors()获取 DataRow 中对象包含的错误数组
Merge()合并指定 DataTable 到当前 DataTable
NewRow()创建一个具有相同的架构 DataRow 对象

6、SqlDataAdapter 对象

SqlDataAdapter(数据适配器)是 DataSet 和 SQL Server 之间的桥接器,对应的类包含在 System.Data.SqlClient 命名空间中。SqlDataAdapter 可以将数据源中的数据填充到 DataSet 中,也可以将 DataSet 中的数据更新到数据源中。

6.1、SqlDataAdapter 类的属性与方法

在 DataSet 与一个或多个数据源进行交互时,SqlDataAdapter 提供了 DataSet 对象和数据源之间的连接。

6.1.1、SqlDataAdapter 类的主要属性

属性名说明
SelectCommand获取或设置 SQL 语句或存储过程的过程在数据源中选择记录
DeleteCommand获取或设置 SQL 语句或存储过程的过程来从数据集中删除数据
InsertCommand获取或设置 SQL 语句或存储过程的过程以将新记录插入到数据源
UpdateCommand获取或设置 SQL 语句或存储过程的过程用于更新数据源中的记录

6.1.2、SqlDataAdapter 类的主要方法

方法名说明
Fill(DataSet)添加或刷新 DataSet 中的对象
Fill(DataSet,String)添加或刷新 DataSet 中指定 DataTable 名称的对象
Fill(DataTable)添加或刷新 DataTable 中的对象
Update(DataSet)执行相应的 insert,update 或 delete 语句将 DataSet 中的内容更新到数据库中
Update(DataSet,String)执行相应的 insert,update 或 delete 语句将 DataSet 内 DataTable 的内容更新到数据库中
Update(DataTable)执行相应的 insert,update 或 delete 语句将 DataTable 的内容更新到数据库中

6.1.3、SqlDataAdapter 类的构造函数

构造函数说明
SqlDataAdapter()初始化 SqlDataAdapter 类的新实例
SqlDataAdapter(SqlCommand)创建实例的对象并初始化 SqlDataAdapter 的 SelectCommand 属性
SqlDataAdapter(String,SqlCommand)创建实例的对象并初始化 SqlDataAdapter 类的 SelectCommand 和 SqlConnection 属性

6.2、使用 SqlDataAdapter 对象获取数据

SqlDataAdapter 的主要作用是填充 DataSet 和更新 SQL Server 数据库,SqlDataAdapter 和 DataSet 之间没有直接连接,当执行 SqlDataAdapter.Fill(DataSet) 方法后,两个对象之间才有连接。SqlDataAdapter 的 Fill 方法调用前不需要打开的 SqlConnection 对象,SqlDataAdapter 会自己打开连接对象中的数据库,获取查询结果后关闭与数据库的连接。

说明:

  1. SqlDataReader 对象和 SqlDataAdapter 对象很相似,都需要有一个数据库连接对象。SqlDataAdapter 对象能够自动打开和关闭连接,而 SqlDataReader 对象需要用户手动管理连接。
  2. DataSet 的最大好处在于能够提供无连接的数据库副本。

6.3、使用 SqlDataAdapter 对象更新数据

SqlDataAdapter 对象的 Fill 方法可以将查询的结果填充为数据集的一个数据表(DataTable)对象,当表内的数据发生变化(增加,修改,删除)后,也可以使用 SqlDataAdapter 对象的 Update 方法将数据在数据库内进行更新。执行时调用预编译好的 insert,delete 和 update 等 SQL 命令更新数据库,使得内存 DataTable 和数据库实际的表格同步。

7、数据库连接模式

通过 ADO.NET 执行数据库操作的过程如下:

  1. 导入相应的命名空间。
  2. 使用 Connection 对象建立与数据库的连接。
  3. 使用 Command 对象或 DataAdapter 对象对数据库执行 SQL 命令,实现对数据库的查询,插入,更新和删除操作。
  4. 通过 DataSet 对象或 DataReader 对象访问数据库。
  5. 使用数据显示控件或输出语句显示数据。

在 ADO.NET 中有两种访问数据库的模式,一种是连接模式,在保持数据库连接的方式下通过执行指定的 SQL 语句完成对数据的操作,数据的操作在断开数据库连接之前;另一种是断开模式,先将数据库中的数据读取到服务器的 DataSet 或者 DataTable 中,数据的操作在断开数据库之后。

7.1、连接模式

7.1.1、使用连接模式访问数据库

  1. 创建 Connection 对象与数据库建立连接。
  2. 创建 Command 对象对数据库执行 SQL 命令或存储过程,包括增,删,改及查询数据库等命令。
  3. 打开与数据库的连接。
  4. 执行操作数据库的命令,如果查询数据库的数据,则创建 DataReader 对象读取 Command 命令查询到的结果集,并将查询到的结果集绑定到控件上。
  5. 关闭与数据库的连接。

7.1.2、操作数据库的两种方法

Command 对象提供了多种完成数据库操作的方法,下面介绍常用的两种方法。
1)ExecuteReader() 方法
ExecuteReader() 方法提供了顺序读取数据的方法,该方法根据提供的 select 语句返回一个 DataReader 对象,开发人员可以使用 DataReader 对象的 Read 方法循环依次读取每条记录中各字段的内容。
2)ExecuteNonQuery() 方法
ExecuteNonQuery() 方法执行 SQL 语句,并返回因操作受影响的行数。一般将其用于 update,insert,delete 或 select 语句直接操作数据库中的表数据。对于 update,insert,delete 语句,ExecuteNonQuery() 方法的返回值为该语句所影响的行数;而对于 select 语句,由于执行 select 语句后数据库并无变化,所以其返回值为 -1。

7.2、断开模式

7.2.1、断开模式概述

DataSet 对象包含多个 DataTable 对象,用于存储与数据源断开连接的数据。DataAdapter 对象可以作为数据库和内存之间的桥梁,使用 DataAdapter 对象的 Fill 方法可以提取查询的结果并填充到 DataTable 中,然后关闭连接,此时处于非连接状态,然后应用程序继续处理离线的 DataSet 数据。

7.2.2、使用断开模式访问数据库

1)使用断开模式查询数据的步骤

  1. 创建 Connection 对象与数据库建立连接。
  2. 创建 DataAdapter 对象,并设置 select 语句。
  3. 创建 DataSet 对象或者 DataTable 对象。
  4. 使用 DataAdapter 的 Fill 方法填充 DataSet。
  5. 使用数据控件对数据进行显示。

2)使用断开模式编辑数据的步骤

  1. 创建 Connection 对象与数据库建立连接。
  2. 创建 DataAdapter 对象,并设置 select 语句。
  3. 创建 CommandBuilder 对象。
  4. 创建 DataSet 对象或者 DataTable 对象。
  5. 使用 DataAdapter 的 Fill 方法填充 DataSet。
  6. 使用数据控件对数据进行插入,更新或删除操作。
  7. 调用 DataAdapter 对象的 Update 方法更新数据库。

说明:

  1. 释放与数据库的连接除了使用 SqlConnection 对象的 Close 方法外,还有一种方法就是使用 using 语句。在 using 语句中不再使用 Close 方法,一旦 using 模块结束,系统立即关闭与相关对象的连接。

7.3、两种访问模式的区别

  • 连接模式是指客户端始终与数据源保持连接,直到程序结束,这种方式的实时性好,但独占数据库连接,在数据量小,只读的情况下优先选择这种模式。
  • 断开模式是指客户端从数据源获取数据后断开与数据源的连接,所有的数据操作都是针对本地数据缓存里的数据,当需要从数据源获取新数据或者被处理后的数据回传时客户端再与数据源连接完成相应的操作。这种方式不独占数据库连接,不过实时性差。断开模式适用于数据量大,需要修改数据同时更新数据库的场合。

8、数据访问帮助类

8.1、DbHelperSql.cs

using System;
using System.Data.SqlClient;
using System.Data;
using System.Collections.Generic;

namespace BMS.Common
{
    public abstract class DbHelperSql
    {
        #region ExecuteNonQuery()
        /// <summary>
        /// 执行SQL命令并返回受影响的行数
        /// 增删改操作调用该方法
        /// </summary>
        /// <param name="connectionString">连接字符串</param>
        /// <param name="cmdType">执行的命令类型,类型值有:Text(SQL命令),StoredProcedure(存储过程),TableDirect(表)</param>
        /// <param name="cmdText">执行的SQL语句,存储过程名称或表名</param>
        /// <param name="parameterNames">参数名数组</param>
        /// <param name="parameterValues">参数值数组</param>
        /// <returns>受影响的行数</returns>
        public static int ExecuteNonQuery(string connectionString, CommandType cmdType, string cmdText, string[] parameterNames, object[] parameterValues)
        {
            using (SqlConnection conn = new SqlConnection(connectionString))
            {
                using (SqlCommand cmd = new SqlCommand())
                {
                    try
                    {
                        PrepareCommand(cmd, conn, null, cmdType, cmdText, parameterNames, parameterValues);
                        int val = cmd.ExecuteNonQuery();
                        cmd.Parameters.Clear();
                        return val;
                    }
                    catch (SqlException ex)
                    {
                        throw ex;
                    }
                }
            }
        }

        /// <summary>
        /// 根据现有数据库连接执行SQL命令并返回受影响的行数 
        /// 增删改操作调用该方法
        /// </summary>
        /// <param name="conn">数据库连接对象</param>
        /// <param name="cmdType">执行的命令类型,类型值有:Text(SQL命令),StoredProcedure(存储过程),TableDirect(表)</param>
        /// <param name="cmdText">执行的SQL语句,存储过程名称或表名</param>
        /// <param name="parameterNames">参数名数组</param>
        /// <param name="parameterValues">参数值数组</param>
        /// <returns>受影响的行数</returns>
        public static int ExecuteNonQuery(SqlConnection conn, CommandType cmdType, string cmdText, string[] parameterNames, object[] parameterValues)
        {
            using (SqlCommand cmd = new SqlCommand())
            {
                try
                {
                    PrepareCommand(cmd, conn, null, cmdType, cmdText, parameterNames, parameterValues);
                    int val = cmd.ExecuteNonQuery();
                    cmd.Parameters.Clear();
                    return val;
                }
                catch (SqlException ex)
                {
                    throw ex;
                }
            }
        }

        /// <summary>
        /// 根据现有数据库事务执行SQL命令并返回受影响的行数
        /// 增删改操作调用该方法
        /// </summary>
        /// <param name="trans">数据库事务</param>
        /// <param name="cmdType">执行的命令类型,类型值有:Text(SQL命令),StoredProcedure(存储过程),TableDirect(表)</param>
        /// <param name="cmdText">执行的SQL语句,存储过程名称或表名</param>
        /// <param name="parameterNames">参数名数组</param>
        /// <param name="parameterValues">参数值数组</param>
        /// <returns>受影响的行数</returns>
        public static int ExecuteNonQuery(SqlTransaction trans, CommandType cmdType, string cmdText, string[] parameterNames, object[] parameterValues)
        {
            using (SqlCommand cmd = new SqlCommand())
            {
                try
                {
                    PrepareCommand(cmd, trans.Connection, trans, cmdType, cmdText, parameterNames, parameterValues);
                    int val = cmd.ExecuteNonQuery();
                    cmd.Parameters.Clear();
                    return val;
                }
                catch (SqlException ex)
                {
                    throw ex;
                }
            }
        }
        #endregion

        #region ExecuteScalar()
        /// <summary>
        /// 执行SQL命令并返回一个标量值,如果在一个常规查询语句中调用该方法,则只返回第一行第一列的值
        /// 返回一个值的查询或Count(*)等聚合函数操作调用该方法
        /// </summary>
        /// <param name="connectionString">连接字符串</param>
        /// <param name="cmdType">执行的命令类型,类型值有:Text(SQL命令),StoredProcedure(存储过程),TableDirect(表)</param>
        /// <param name="cmdText">执行的SQL语句,存储过程名称或表名</param>
        /// <param name="parameterNames">参数名数组</param>
        /// <param name="parameterValues">参数值数组</param>
        /// <returns>标量值或第一行第一列的值,类型为object,可以使用Convert.To{Type}转换为期望类型</returns>
        public static object ExecuteScalar(string connectionString, CommandType cmdType, string cmdText, string[] parameterNames, object[] parameterValues)
        {
            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                using (SqlCommand cmd = new SqlCommand())
                {
                    try
                    {
                        PrepareCommand(cmd, connection, null, cmdType, cmdText, parameterNames, parameterValues);
                        object val = cmd.ExecuteScalar();
                        cmd.Parameters.Clear();
                        return val;
                    }
                    catch (SqlException ex)
                    {
                        throw ex;
                    }
                }

            }
        }
        #endregion

        #region ExecuteReader()
        /// <summary>
        /// 执行SQL命令并返回一个SqlDataReader对象 
        /// </summary>
        /// <param name="connectionString">连接字符串</param>
        /// <param name="cmdType">执行的命令类型,类型值有:Text(SQL命令),StoredProcedure(存储过程),TableDirect(表)</param>
        /// <param name="cmdText">执行的SQL语句,存储过程名称或表名</param>
        /// <param name="parameterNames">参数名数组</param>
        /// <param name="parameterValues">参数值数组</param>
        /// <returns>SqlDataReader对象</returns>
        public static SqlDataReader ExecuteReader(string connectionString, CommandType cmdType, string cmdText, string[] parameterNames, object[] parameterValues)
        {
            SqlConnection conn = new SqlConnection(connectionString);
            using (SqlCommand cmd = new SqlCommand())
            {
                try
                {
                    PrepareCommand(cmd, conn, null, cmdType, cmdText, parameterNames, parameterValues);
                    SqlDataReader sdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
                    cmd.Parameters.Clear();
                    return sdr;
                }
                catch (SqlException ex)
                {
                    conn.Close();
                    throw ex;
                }
            }
        }
        #endregion

        #region SqlDataAdapter()
        /// <summary>
        /// 执行SQL命令并返回一个DataTable数据表对象
        /// 查询一个数据表并返回该数据表操作调用该方法
        /// </summary>
        /// <param name="connectionString">连接字符串</param>
        /// <param name="cmdType">执行的命令类型,类型值有:Text(SQL命令),StoredProcedure(存储过程),TableDirect(表)</param>
        /// <param name="cmdText">执行的SQL语句,存储过程名称或表名</param>
        /// <param name="dtName">DataTable表名</param>
        /// <param name="parameterNames">参数名数组</param>
        /// <param name="parameterValues">参数值数组</param>
        /// <returns>DataTable数据表对象</returns>
        public static DataTable GetDataTable(string connectionString, CommandType cmdType, string cmdText, string dtName, string[] parameterNames, object[] parameterValues)
        {
            DataSet ds = GetDataSet(connectionString, cmdType, cmdText, dtName, parameterNames, parameterValues);
            DataTable dt = null;
            if (ds != null && ds.Tables.Count > 0)
            {
                dt = ds.Tables[dtName];
            }
            return dt;
        }

        /// <summary>
        /// 执行SQL命令并返回一个DataSet数据集对象
        /// 查询一个数据集并返回该数据集操作调用该方法
        /// </summary>
        /// <param name="connectionString">连接字符串</param>
        /// <param name="cmdType">执行的命令类型,类型值有:Text(SQL命令),StoredProcedure(存储过程),TableDirect(表)</param>
        /// <param name="cmdText">执行的SQL语句,存储过程名称或表名</param>
        /// <param name="dtName">DataTable表名</param>
        /// <param name="parameterNames">参数名数组</param>
        /// <param name="parameterValues">参数值数组</param>
        /// <returns>DataSet数据集对象</returns>
        public static DataSet GetDataSet(string connectionString, CommandType cmdType, string cmdText, string dtName, string[] parameterNames, object[] parameterValues)
        {
            using (SqlConnection conn = new SqlConnection(connectionString))
            {
                using (SqlCommand cmd = new SqlCommand())
                {
                    PrepareCommand(cmd, conn, null, cmdType, cmdText, parameterNames, parameterValues);
                    using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
                    {
                        try
                        {
                            DataSet ds = new DataSet();
                            sda.Fill(ds, dtName);
                            cmd.Parameters.Clear();
                            return ds;
                        }
                        catch (SqlException ex)
                        {
                            throw ex;
                        }
                    }
                }
            }
        }
        #endregion

        #region BeginTransaction()
        /// <summary>
        /// 执行多条SQL语句实现数据库事务
        /// </summary>
        /// <param name="connectionString">连接字符串</param>
        /// <param name="sqlStringList">执行的SQL语句集合</param>
        /// <returns>受影响的行数</returns>
        public static int BeginTransaction(string connectionString, List<String> sqlStringList)
        {
            using (SqlConnection conn = new SqlConnection(connectionString))
            {
                using (SqlCommand cmd = new SqlCommand())
                {
                    conn.Open();
                    SqlTransaction trans = conn.BeginTransaction();
                    cmd.Connection = conn;
                    cmd.Transaction = trans;
                    try
                    {
                        int val = 0;
                        for (int i = 0; i < sqlStringList.Count; i++)
                        {
                            cmd.CommandText = sqlStringList[i];
                            val += cmd.ExecuteNonQuery();
                        }
                        trans.Commit();
                        return val;
                    }
                    catch
                    {
                        trans.Rollback();
                        return 0;
                    }
                }
            }
        }
        #endregion

        #region SqlBulkCopy()
        /// <summary>
        /// 使用SqlBulkCopy批量插入
        /// </summary>
        /// <param name="connectionString">连接字符串</param>
        /// <param name="dt">DataTable数据源</param>
        /// <param name="tableName">要插入的数据库表名</param>
        /// <returns>插入的行数</returns>
        public static int SqlBulkCopy(string connectionString, DataTable dt, string tableName)
        {
            using (SqlConnection conn = new SqlConnection(connectionString))
            {
                if (conn.State == ConnectionState.Closed)
                {
                    conn.Open();
                }
                using (SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(conn))
                {
                    //数据库表名
                    sqlBulkCopy.DestinationTableName = tableName;
                    for (int i = 0; i < dt.Columns.Count; i++)
                    {
                        //将DataTable中的列与数据库表中的列一一对应
                        sqlBulkCopy.ColumnMappings.Add(dt.Columns[i].ColumnName, dt.Columns[i].ColumnName);
                    }
                    try
                    {
                        sqlBulkCopy.WriteToServer(dt);
                        return dt.Rows.Count;
                    }
                    catch
                    {
                        return 0;
                    }
                }
            }
        }

        /// <summary>
        /// 使用数据库事务和SqlBulkCopy批量插入
        /// </summary>
        /// <param name="connectionString">连接字符串</param>
        /// <param name="dt">DataTable数据源</param>
        /// <param name="tableName">要插入的数据库表名</param>
        /// <returns>插入的行数</returns>
        public static int TransSqlBulkCopy(string connectionString, DataTable dt, string tableName)
        {
            using (SqlConnection conn = new SqlConnection(connectionString))
            {
                if (conn.State == ConnectionState.Closed)
                {
                    conn.Open();
                }
                //开启事务
                SqlTransaction trans = conn.BeginTransaction();
                using (SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(conn, SqlBulkCopyOptions.CheckConstraints, trans))
                {
                    //数据库表名
                    sqlBulkCopy.DestinationTableName = tableName;
                    foreach (DataColumn dc in dt.Columns)
                    {
                        //将DataTable中的列与数据库表中的列一一对应
                        sqlBulkCopy.ColumnMappings.Add(dc.ColumnName, dc.ColumnName);
                    }
                    try
                    {
                        sqlBulkCopy.WriteToServer(dt);
                        trans.Commit();
                        return dt.Rows.Count;
                    }
                    catch
                    {
                        trans.Rollback();
                        return 0;
                    }
                }
            }
        }
        #endregion

        /// <summary>
        /// 数据库命令对象SqlCommand设置属性
        /// </summary>
        /// <param name="cmd">数据库命令对象SqlCommand</param>
        /// <param name="conn">数据库连接对象SqlConnection</param>
        /// <param name="trans">数据库事务对象SqlTransaction</param>
        /// <param name="cmdType">执行的命令类型,类型值有:Text(SQL命令),StoredProcedure(存储过程),TableDirect(表)</param>
        /// <param name="cmdText">执行的SQL语句,存储过程名称或表名</param>
        /// <param name="parameterNames">参数名数组</param>
        /// <param name="parameterValues">参数值数组</param>
        private static void PrepareCommand(SqlCommand cmd, SqlConnection conn, SqlTransaction trans, CommandType cmdType, string cmdText, string[] parameterNames, object[] parameterValues)
        {
            //连接是否处于打开状态
            if (conn.State != ConnectionState.Open)
            {
                //打开数据库连接
                conn.Open();
            }
            cmd.Connection = conn;
            cmd.CommandText = cmdText;
            if (trans != null)
            {
                cmd.Transaction = trans;
            }
            cmd.CommandType = cmdType;
            if (parameterNames != null)
            {
                for (int i = 0; i < parameterNames.Length; i++)
                {
                    //SQL中的null对应于C#中的DBNull.Value
                    cmd.Parameters.AddWithValue(parameterNames[i], parameterValues[i] ?? DBNull.Value);
                }
            }
        }
    }
}

8.2、DbHelper.cs

using System;
using System.Configuration;
using System.Data;
using System.Collections.Generic;

namespace BMS.Common
{
    public abstract class DbHelper
    {
        /// <summary>
        /// 连接字符串,可以写在程序代码中,也可以写在网站的配置文件 Web.config 文件中
        /// </summary>
        public static readonly string sqlConnectionString = ConfigurationManager.ConnectionStrings["sqlConnectionString"].ToString();

        /// <summary>
        /// 执行SQL语句并返回受影响的行数
        /// 增删改操作调用该方法
        /// </summary>
        /// <param name="sqlString">SQL语句</param>
        /// <param name="parameterNames">参数名数组</param>
        /// <param name="parameterValues">参数值数组</param>
        /// <returns>受影响的行数</returns>
        public static int ExecuteNonQuery(string sqlString, string[] parameterNames, object[] parameterValues)
        {
            return DbHelperSql.ExecuteNonQuery(sqlConnectionString, CommandType.Text, sqlString, parameterNames, parameterValues);
        }

        /// <summary>
        /// 执行SQL语句并返回一个标量值,如果在一个常规查询语句中调用该方法,则只返回第一行第一列的值
        /// 返回一个值的查询或Count(*)等聚合函数操作调用该方法
        /// </summary>
        /// <param name="sqlString">SQL语句</param>
        /// <param name="parameterNames">参数名数组</param>
        /// <param name="parameterValues">参数值数组</param>
        /// <returns>标量值或第一行第一列的值,类型为object,可以使用Convert.To{Type}转换为期望类型</returns>
        public static object ExecuteScalar(string sqlString, string[] parameterNames, object[] parameterValues)
        {
            return DbHelperSql.ExecuteScalar(sqlConnectionString, CommandType.Text, sqlString, parameterNames, parameterValues);
        }

        /// <summary>
        /// 执行SQL语句并返回一个DataTable数据表对象
        /// 排序分页查询操作调用该方法(单表)
        /// </summary>
        /// <param name="tableName">要操作的表名称</param>
        /// <param name="where">查询条件,形如:"and Field_Name>0"</param>
        /// <param name="order">排序,形如:"Field_Name asc"</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">每页数量</param>
        /// <returns>DataTable数据表对象</returns>
        public static DataTable QueryOrderPage(string tableName, string where, string order, int pageIndex, int pageSize)
        {
            String sqlString = string.Format("select * from {0} " +
               "where 1=1 {1} " +
              "order by {2} offset {3} rows fetch next {4} rows only", tableName, where, order, (pageIndex - 1) * pageSize, pageSize);
            DataTable dt = GetDataTable(sqlString, null, null);
            return dt;
        }

        /// <summary>
        /// 执行SQL语句并返回一个DataTable数据表对象
        /// 排序分页查询操作调用该方法(多表联查)
        /// </summary>
        /// <param name="sqlStr">SQL语句,形如:"select a.*,b.field_bn,c.field_cn from tableA a left join tableB b on b.field_b=a.field_b left join tableC c on c.field_c=a.field_c where a.field=0 and b.field=0 and c.field=0"</param>
        /// <param name="where">查询条件,形如:"and field>0"</param>
        /// <param name="order">排序,形如:"field asc"</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">每页数量</param>
        /// <returns>DataTable数据表对象</returns>
        public static DataTable QueryJoinOrderPage(string sqlStr, string where, string order, int pageIndex, int pageSize)
        {
            string sqlString = string.Format("select * from" +
                "(select *,ROW_NUMBER() over(order by {2}) Row_Number from" +
                "({0})tb1 where 1=1 {1})tb2 " +
                "where tb2.Row_Number between {3} and {4}", sqlStr, where, order, (pageIndex - 1) * pageSize + 1, pageIndex * pageSize);
            DataTable dt = GetDataTable(sqlString, null, null);
            return dt;
        }

        /// <summary>
        /// 执行SQL语句并返回一个DataTable数据表对象
        /// </summary>
        /// <param name="sqlString">SQL语句</param>
        /// <param name="parameterNames">参数名数组</param>
        /// <param name="parameterValues">参数值数组</param>
        /// <returns>DataTable数据表对象</returns>
        public static DataTable GetDataTable(string sqlString, string[] parameterNames, object[] parameterValues)
        {
            return DbHelperSql.GetDataTable(sqlConnectionString, CommandType.Text, sqlString, "dt", parameterNames, parameterValues);
        }

        /// <summary>
        /// 数据库事务执行多条SQL语句
        /// </summary>
        /// <param name="sqlStringList">执行的SQL语句集合</param>
        /// <returns>受影响的行数</returns>
        public static int ExecuteSqlTrans(List<String> sqlStringList)
        {
            return DbHelperSql.BeginTransaction(sqlConnectionString, sqlStringList);
        }

        /// <summary>
        /// 使用SqlBulkCopy批量插入
        /// </summary>
        /// <param name="dt">DataTable数据源</param>
        /// <param name="tableName">要插入的数据库表名</param>
        /// <returns>插入的行数</returns>
        public static int SqlBulkCopy(DataTable dt, string tableName)
        {
            return DbHelperSql.SqlBulkCopy(sqlConnectionString, dt, tableName);
        }

        /// <summary>
        /// 使用数据库事务和SqlBulkCopy批量插入
        /// </summary>
        /// <param name="dt">DataTable数据源</param>
        /// <param name="tableName">要插入的数据库表名</param>
        /// <returns>插入的行数</returns>
        public static int TransSqlBulkCopy(DataTable dt, string tableName)
        {
            return DbHelperSql.TransSqlBulkCopy(sqlConnectionString, dt, tableName);
        }
    }
}
  • 1
    点赞
  • 0
    评论
  • 5
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值