ADO.NET
是在用于直接满足用户开发可伸缩应用程序需求的
ADO
数据访问模型的基础上发展而来的。它是专门为
Web
设计的,并且考虑了伸缩性,无状态性和
XML
的问题。
ADO.NET
使用了某些
ADO
的对象,如
Connection
和
Command
对象,并且还引入了新的对象。主要的新
ADO.NET
对象包括
DataSet
、
DataReader
和
DataAdapter
。
ADO.NET
这一发展版本与以前的数据结构之间的重要区别就是
DataSet
对象的存在,该对象独立于任何数据存储区并且与之不同。正因为如此,
DataSet
对象作为一个独立实体运行。可以将数据集
(DataSet)
设想为始终断开的记录集,它对其所包含的数据的源或目标一无所知。
DataSet
的里面很像数据库,有表、列、关系、约束、视图,等等。
DataAdapter
连接到数据库以填充
DataSet
的对象。然后,它又连接回数据库,根据
DataSet
保留数据时所执行的操作来更新数据库中的该数据。在过去,数据处理主要是基于连接的。现在,为了使多层应用程序更为高效,数据处理正转向基于消息的方式,围绕信息块进行处理。这种方式的中心是
DataAdapter
,它起着桥梁的作用,在
DataSet
和其源数据存储区之间进行数据检索和保存。这一操作是通过请求对数据存储区进行适当的
SQL
命令来完成的。
基于
XML
的
DataSet
对象提供一致的编程模型,该模型可配合所有的数据存储模型使用,无论是单层的、关系型的、还是分层的。为做到这一点,
DataSet
对象对其数据源
“
一无所知
”
,并且将它拥有的数据表示为集合和数据类型。无论
DataSet
中数据的源是什么,它都是通过由
DataSet
与其从属对象所公开的同一套标准
API
来操纵的。
虽然
DataSet
对其数据的源一无所知,但托管提供程序具有详细而具体的信息。托管提供程序的作用是在
DataSet
与数据存储区之间来回进行连接、填充和保持。
OLE DB
数据提供者与
SQL Server .NET
数据提供者(
System.Data.OleDb
和
System.Data.SqlClient
)是
.Net
框架的一部分,它们提供四个基本对象:
Command
、
Connection
、
DataReader
和
DataAdapter
。在本文档的余下部分,我们将介绍
DataSet
和
OLE DB/SQL Server .NET
数据提供程序的每一部分,解释它们是什么以及如何对它们进行编程。
以下部分将向您介绍一些对象,其中有些是经过发展的,有些是全新的。这些对象如下:
·
Connection
。用于连接到数据库和管理对数据库的事务。
·
Command
。用于对数据库发出
SQL
命令。
·
DataReader
。用于从
SQL Server
数据源读取只进数据记录流。
·
DataSet
。用于对单层数据、
XML
数据和关系数据进行存储、远程处理和编程。
·
DataAdapter
。用于将数据推入
DataSet
,并使数据与数据库保持一致。
注意
当处理到数据库的连接时,有两个不同的选项:
SQL Server .NET
数据提供程序
(System.Data.SqlClient)
和
OLE DB .NET
数据提供程序
(System.Data.OleDb)
。在这些示例中,我们将使用
SQL Server .NET
数据提供程序。这些示例的是为了直接与
Microsoft SQL Server
交互。
OLE DB .NET
数据提供程序则用于与任何
OLE DB
提供程序交互(因为它在底层使用
OLE DB
)。
Connection
(连接)
连接用于与数据库
“
对话
”
,并由
SQLConnection
等特定于提供程序的类来表示。命令
(Command)
将遍历连接并以流的形式返回结果集,该结果集可由
DataReader
对象读取,或是被推入
DataSet
对象。
下面的示例说明如何创建连接对象。可通过调用连接上的
Open
方法来显式打开连接,也可在使用
DataAdapter
时隐式打开连接。
namespace HowTo.Samples.ADONET
{
using System;
using System.Data.SqlClient;
public class adooverview1
{
publicstaticvoid Main()
{
adooverview1 myadooverview1 = new adooverview1();
myadooverview1.Run();
}
publicvoid Run()
{
SqlConnection mySqlConnection = new SqlConnection("server=(local)//NetSDK;Trusted_Connection=yes;database=northwind");
try
{
mySqlConnection.Open();
Console.WriteLine("打开的连接 {0} ", mySqlConnection.ConnectionString);
// Close the connection explicitly
mySqlConnection.Close();
Console.WriteLine("已关闭。显式地关闭连接是很重要的。");
}
catch
{
Console.WriteLine("未能打开到 {0} 的连接", mySqlConnection.ConnectionString);
}
}
}
}
Command
(命令)
命令包含向数据库提交的信息,并且由
SQLCommand
等特定于提供程序的类来表示。命令可以是存储过程调用、
UPDATE
语句或返回结果的语句。还可将输入和输出参数、以及返回值用作命令语法的一部分。下面的示例说明如何对
Northwind
数据库发出
INSERT
语句。
namespace HowTo.Samples.ADONET
{
using System;
using System.Data.SqlClient;
public class adooverview2
{
publicstaticvoid Main()
{
adooverview2 myadooverview2 = new adooverview2();
myadooverview2.Run();
}
publicvoid Run()
{
string Message = null;
SqlConnection myConnection = new SqlConnection("server=(local)//NetSDK;Trusted_Connection=yes;database=northwind");
SqlCommand mySqlCommand = new SqlCommand("INSERT INTO Customers (CustomerId, CompanyName, ContactName, ContactTitle, Address) Values ('ABC','ABC Company', 'John Smith', 'Owner','One My Way')", myConnection);
SqlCommand mySqlCleanup = new SqlCommand("DELETE FROM Customers WHERE CustomerId = 'ABC'", myConnection);
try
{
myConnection.Open();
mySqlCleanup.ExecuteNonQuery(); // remove record that may have been entered previously.
mySqlCommand.ExecuteNonQuery();
Message = "新记录已插入 northwind 中的 Customers 表。";
}
catch(Exception e)
{
Message= "未能插入记录:" + e.ToString();
}
finally
{
myConnection.Close();
}
Console.Write(Message);
}
}
}
DataReader对象对于数据有点像只读/只进游标。DataReader API 既支持平面数据,也支持分层数据。在对数据库执行命令之后返回一个 DataReader 对象。返回的 DataReader 对象的格式与记录集不同。例如,您可能会使用 DataReader 在 Web 页上显示搜索列表的结果。
namespace HowTo.Samples.ADONET
{
using System;
using System.Data;
using System.Data.SqlClient;
public class adooverview3
{
publicstaticvoid Main()
{
adooverview3 myadooverview3 = new adooverview3();
myadooverview3.Run();
}
publicvoid Run()
{
SqlDataReader myReader = null;
SqlConnection mySqlConnection = new SqlConnection("server=(local)//NetSDK;Trusted_Connection=yes;database=northwind");
SqlCommand mySqlCommand = new SqlCommand("select * from customers", mySqlConnection);
try
{
mySqlConnection.Open();
myReader = mySqlCommand.ExecuteReader();
Console.Write("客户 ID ");
Console.WriteLine("公司名称");
while (myReader.Read())
{
Console.Write(myReader["CustomerId"].ToString() + " ");
Console.WriteLine(myReader["CompanyName"].ToString());
}
}
catch(Exception e)
{
Console.WriteLine(e.ToString());
}
finally
{
if (myReader != null)
myReader.Close();
if (mySqlConnection.State == ConnectionState.Open)
mySqlConnection.Close();
}
}
}
}
DataSet
DataSet 对象与 ADO Recordset 对象相似,但功能更为强大,并具有另一重要区别:DataSet始终是断开的。DataSet对象表示数据的缓存,具有类似数据库的结构,如表、列、关系和约束。但是,尽管 DataSet 可以并且的确像数据库那样运行,但重要的是要记住:DataSet对象不直接与数据或其他源数据进行交互。这使得开发人员能够使用始终保持一致的编程模型,而不用理会源数据的驻留位置。所有来自于数据库、XML 文件、代码或用户输入的数据都可添加到 DataSet 对象中。这样,由于对 DataSet 进行了更改,所以在更新源数据之前可以对这些更改进行跟踪和验证。DataSet对象的 GetChanges 方法实际上是创建了另一个 DatSet,该 DatSet 只包含对数据做出的更改。然后,DataAdapter(或其他对象)使用此 DataSet 来更新原始的数据源。
DataSet 对象与 ADO Recordset 对象相似,但功能更为强大,并具有另一重要区别:DataSet始终是断开的。DataSet对象表示数据的缓存,具有类似数据库的结构,如表、列、关系和约束。但是,尽管 DataSet 可以并且的确像数据库那样运行,但重要的是要记住:DataSet对象不直接与数据或其他源数据进行交互。这使得开发人员能够使用始终保持一致的编程模型,而不用理会源数据的驻留位置。所有来自于数据库、XML 文件、代码或用户输入的数据都可添加到 DataSet 对象中。这样,由于对 DataSet 进行了更改,所以在更新源数据之前可以对这些更改进行跟踪和验证。DataSet对象的 GetChanges 方法实际上是创建了另一个 DatSet,该 DatSet 只包含对数据做出的更改。然后,DataAdapter(或其他对象)使用此 DataSet 来更新原始的数据源。
DataSet具有许多 XML 特性,包括生成和使用 XML 数据和 XML 架构的能力。XML 架构可以用来描述通过 WebServices 交换的架构。实际上,为了类型安全和语句结束,可以对带有架构的 DataSet 进行编译。
DataAdapter (OLEDB/SQL)
DataAdapter 对象在 DataSet 与源数据之间起到桥梁的作用。在使用 Microsoft SQL Server 数据库时,使用提供程序特定的 SqlDataAdapter(以及与其关联的 SqlCommand 和 SqlConnection)能够提高整体性能。对于其他支持 OLE DB 的数据库,将使用 OleDbDataAdapter 对象及其关联 OleDbCommand 和 OleDbConnection 对象。
DataAdapter 对象在 DataSet 与源数据之间起到桥梁的作用。在使用 Microsoft SQL Server 数据库时,使用提供程序特定的 SqlDataAdapter(以及与其关联的 SqlCommand 和 SqlConnection)能够提高整体性能。对于其他支持 OLE DB 的数据库,将使用 OleDbDataAdapter 对象及其关联 OleDbCommand 和 OleDbConnection 对象。
在更改
DataSet
之后,
DataAdapter对象使用命令来更新数据源。使用 DataAdapter 的 Fill 方法调用 SELECT 命令;使用 Update 方法为每一发生更改的行调用 INSERT、UPDATE 或 DELETE 命令。可显式设置这些命令,以控制运行时用来解析更改的语句,包括对存储过程的使用。在特殊情况下,CommandBuilder对象可以根据 Select 语句在运行时生成这些命令。但是,在运行时生成需要一个额外的服务器往返以收集元数据,所以在设计时显式提供 INSERT、UPDATE 和 DELETE 命令将会获得更佳的运行时性能。
SqlConnection myConnection = new SqlConnection("server=(local)/VSdotNET;Trusted_Connection=yes;database=northwind");
SqlDataAdapter mySqlDataAdapter = new SqlDataAdapter("select * from customers", myConnection);
mySqlDataAdapter.InsertCommand.CommandText = "sp_InsertCustomer";
mySqlDataAdapter.InsertCommand.CommandType = CommandType.StoredProcedure;
mySqlDataAdapter.DeleteCommand.CommandText = "sp_DeleteCustomer";
mySqlDataAdapter.DeleteCommand.CommandType = CommandType.StoredProcedure;
mySqlDataAdapter.UpdateCommand.CommandText = "sp_UpdateCustomers";
mySqlDataAdapter.UpdateCommand.CommandType = CommandType.StoredProcedure;
mySqlDataAdapter.Update(myDataSet);
记录将适当地映射到相应的给定命令。
图: DataAdapter 和 DataSet
以下示例阐释了通过
SELECT
语句加载一个
DataAdapter
。然后它在
DataSet
中更新、删除和添加一些记录。最后,通过
DataAdapter
将那些更新返回到源数据库。构造的
DeleteCommand
、
InsertCommand
和
UpdateCommand
将显示在页中。它还阐释了使用多个
DataAdapter
对象将多个表(
Customers
和
Orders
)加载到
DataSet
中。
namespace HowTo.Samples.ADONET
{
using System;
using System.Data;
using System.Data.SqlClient;
public class adooverview4
{
publicstaticvoid Main()
{
adooverview4 myadooverview4 = new adooverview4();
myadooverview4.Run();
}
publicvoid Run()
{
// Create a new Connection and SqlDataAdapter
SqlConnection myConnection = new SqlConnection("server=(local)//NetSDK;Trusted_Connection=yes;database=northwind");
SqlDataAdapter mySqlDataAdapter = new SqlDataAdapter("Select * from Region", myConnection);
SqlParameter workParam = null;
// Restore database to it's original condition so sample will work correctly.
Cleanup();
// Build the insert Command
mySqlDataAdapter.InsertCommand = new SqlCommand("Insert into Region (RegionID, RegionDescription) VALUES (@RegionID, @RegionDescription)", myConnection);
workParam = mySqlDataAdapter.InsertCommand.Parameters.Add("@RegionID", SqlDbType.Int);
workParam.SourceColumn = "RegionID";
workParam.SourceVersion = DataRowVersion.Current;
workParam = mySqlDataAdapter.InsertCommand.Parameters.Add("@RegionDescription", SqlDbType.NChar, 50);
workParam.SourceVersion = DataRowVersion.Current;
workParam.SourceColumn = "RegionDescription";
// Build the update command
mySqlDataAdapter.UpdateCommand = new SqlCommand("Update Region Set RegionDescription = @RegionDescription WHERE RegionID = @RegionID" , myConnection);
workParam = mySqlDataAdapter.UpdateCommand.Parameters.Add("@RegionID", SqlDbType.Int);
workParam.SourceColumn = "RegionID";
workParam.SourceVersion = DataRowVersion.Original;
workParam = mySqlDataAdapter.UpdateCommand.Parameters.Add("@RegionDescription", SqlDbType.NChar, 50);
workParam.SourceVersion = DataRowVersion.Current;
workParam.SourceColumn = "RegionDescription";
DataSet myDataSet = new DataSet();
// Set the MissingSchemaAction property to AddWithKey because Fill will not cause primary key & unique key information to be retrieved unless AddWithKey is specified.
mySqlDataAdapter.MissingSchemaAction = MissingSchemaAction.AddWithKey;
mySqlDataAdapter.Fill(myDataSet, "Region");
DataRow myDataRow1 = myDataSet.Tables["Region"].Rows.Find(2);
myDataRow1[1] = "已更改此地区说明";
DataRow myDataRow2 = myDataSet.Tables["Region"].NewRow();
myDataRow2[0] = 901;
myDataRow2[1] = "新地区";
myDataSet.Tables["Region"].Rows.Add(myDataRow2);
try
{
mySqlDataAdapter.Update(myDataSet, "Region");
Console.Write("已成功更新数据集!");
}
catch(Exception e)
{
Console.Write(e.ToString());
}
}
publicvoid Cleanup()
{
SqlConnection myConnection = new SqlConnection("server=(local)//NetSDK;Trusted_Connection=yes;database=northwind");
try
{
// Restore database to it's original condition so sample will work correctly.
myConnection.Open();
SqlCommand CleanupCommand = new SqlCommand("DELETE FROM Region WHERE RegionID = '901'", myConnection);
CleanupCommand.ExecuteNonQuery();
}
catch(Exception e)
{
Console.Write(e.ToString());
}
finally
{
myConnection.Close();
}
}
}
}
本节小结
1.
ADO.NET
是用于
.Net
框架的
ADO
下一代版本。
2.
ADO.NET
是以
N
层、无状态性和
XML
为突出重点来创建的。这些方案中提供了两个新对象:
DataSet
和
DataAdapter
。
3.
ADO.NET
可用来从流中获取数据,或将数据存储在缓存中以便更新。
4.
本文档中还有有关
ADO.NET
的更多信息。
5.
请记住,可以直接对数据库执行命令,以进行插入、更新和删除操作。无需先将数据放入
DataSet
中即可对其进行插入、更新或删除操作。
6.
此外,可以使用
DataSet
来绑定到数据、在数据间移动和定位数据关系。