数据库-ADONET-使用DataAdapter对象

 

DataAdapter

如果想将查询结果存储在DataSetDataTable对象中,比较简单的是使用DataAdapter对象。

1          DataAdapter对象

DataAdapter类是ADO.NET对象模型中联机和脱机这两部分的桥梁。

l         DataAdapter能将数据从数据库取出,再放到DataSet中;

l         DataAdapter还可以提取DataSet中存储在缓存中的更新数据,并提交给数据库

1.1         DataAdapter特性

DataAdapter对象,感觉上,好像与ADOCommand对象、RDOrdoQuery对象、DAOQueryDef对象相似;但是它们的差异明显。

1.1.1            DataAdapter的设计目的是处理脱机数据

DataAdapter是专门为处理脱机数据而设计的。

最好的例子是Fill方法,调用Fill方法可以不需要DataAdapter拥有与数据库间的活动连接:若在当前未开放的连接上调用FillDataAdapter会开发连接、查询数据库,然后填充结果到DataSet,最后关闭连接。

1.1.2            DataAdapterDataSet间没有直接连接

DataAdapter对象的Fill方法中传递DataSet对象作为参数,可以填充DataSet中的DataTable

l         代码:

OleDbDataAdapter.Fill(DataSet)

调用Fill完成后,两个对象之间就没有连接了。(DataSet不会保存任何内在的或外在的对DataAdapter的引用;DataAdapter也不会保留对DataSet的引用);DataSet不包含任何表明数据来源的信息(例如:连接字符串、表格名、列名称)。

因此,可以将DataSet对象从中间层服务器传递到客户端应用程序,不必担心泄露关于数据库位置与结构的信息。

1.1.3            DataAdapter中能包含回递给数据库的更新逻辑(存储在DataSet中)

DataAdapter也可以向数据库回递待定的更改。(这是与过去的数据访问模型的主要区别)

使用DataAdapterUpdate方法提交更改。调用时需要DataSet对象作为参数。(DataSet能够缓存更改)

注意:实际的更新逻辑包含在DataAdapter对象中。

1.1.4            控制DataAdapter的更新逻辑

DataAdapter中,可以自定义insertupdatedelete查询,或使用存储过程提交更新。

DataAdapter拥有四项属性包含了Command对象,通过它们就可以分别指定自己的操作查询或存储过程;同样也可以分别指定能将数据在DataSet和存储过程之间来回移动的参数。

1.2         DataAdapter剖析(研究它的结构以及运作方式)

DataAdapter的设计目的在于帮助你将查询结果存储在DataSet对象和DataTable对象之中。

Command对象允许通过DataReader对象浏览查询结果。

DataAdapter对象由一系列Command对象组成,还包括一组用于确定DataAdapterDataSet通信关系的映射属性。

1.2.1            子命令

使用DataAdapter将查询结果存储在DataSet中时,DataAdapter会使用一个Command对象来与数据库通讯;DataAdapter对象内在的使用了DataReader来取得结果数据,然后将信息复制到DataSet的新行去。(用循环逐行)

DataAdapter对象取数据的Command对象在其SelectCommand属性中。

插入数据的Command在其InsertCommand属性;删除数据的Command在其DeleteCommand属性;更新数据的Command在其UpdateCommand属性。

1.2.2            TableMapping集合

默认时,DataAdapter假设DataReader中的列与DataSet中的列是相匹配的。

如果,你希望DataSet的架构与数据库中的架构不同(一种可能是想给DataSet中的特定列使用不同的名称):传统作法是,在查询中给列指定别名;现在,你可以使用TableMappings集合机制。

DataAdapter对象的TableMappings集合允许创建一个数据库和DataSet之间的映射层。

TableMappings属性返回一个DataTableMappingsCollection对象。

DataTableMappingsCollection对象含有一组DataTableMapping对象,其中每个对象都允许你在数据库中的某一个表(或视图、存储过程)与DataSet相应表之间创建映射。

DataTableMapping对象含有一个ColumnMappings属性,它返回一个DataColumnMappingCollection对象。

DataColumnMappingCollection对象是由一组DataColumnMapping对象组成的集合,每一个DataColumnMapping都能将数据库一列映射为DataSet一列。

 

l         代码演示(填充TableMappings集合)

Dim da As OleDbAdapter

初始化Adapter

Dim tblMap as DataTableMapping

Dim colMap as DataColumnMapping

将表名对应

tblMap=da.TableMappings.Add(“Table”,”Employee”)

将列名对应

colMap=tblMap.ColumnMappings.Add(“EmpID”,”EmployeeID”)

colMap=tblMap.ColumnMappings.Add(“LName”,”LastName”)

colMap=tblMap.ColumnMappings.Add(“FName”,”FirstName”)

2          创建和使用DataAdapter对象

2.1         创建DataAdapter

注意:创建DataAdapter对象时,一般都希望SelectCommand属性是可用的Command对象。

l         代码

Dim strConn as String=”…”

Dim cn as new OleDbConnection(strConn)

Dim ssql as string=”select CustomerID,CompanyName from Customers”

Dim cmd as new OleDbCommand(ssql,cn)

Dim da as new OleDbAdapter()

da.SelectCommand=cmd

2.2         DataAdapter的构造函数

DataAdapter4个构造函数(3个是带参数的):

l              Public Sub New(ByVal selectCommand As OleDbCommand)

使用一个存在的Command作为SelectCommand使用

l              Public Sub New(ByVal selectCommandText As String, ByVal selectConnection As OleDbConnection)

使用一个存在的Connection连接对象,并根据传入的查询SQL潜在的构造SelectCommand对象

l              Public Sub New(ByVal selectCommandText As String, ByVal selectConnectionString As String)

此构造函数,潜在的为新DataAdapter构造一个Connection对象,并潜在的构造SelectCommand对象。

2.3         从查询中取得结果

2.3.1            使用Fill方法

调用Fill会:

1.        执行存储在SelectCommand属性中的查询

2.        将查询结果存储在DataSet中,如果未指定,则数据放在新创建的默认的DataTable对象(名Tabe

n         代码:

Dim strConn,strSql as String

strConn=”…”

strSql=”Select CustomerID,CompanyName,ContactName,Phone from Customers”

Dim da as New OleDbDataAdapter(strSql,strConn)

Dim ds As new DataSet()

da.Fill(ds)

2.3.2            使用Fill方法创建DataTable对象和DataColumn对象

Fill方法会在DataSet对象中创建新的DataTable(如果没有指定DataTable名的话默认为‘Table’)此DataTable的列结构与查询结果相同。

TableMappings集合中添加新TableMapping项目可以修改查询结果,改变其映射关系。

n         代码

Dim da as new OleDbDataAdapter(strSql,strConn)

Da.TableMappings.Add(“Table”,”Customers”) ‘此处将查询结果映射到名叫CustomersDataTable

Dim ds as new DataSet()

da.Fill(ds)

2.3.3            使用重载的Fill方法

Fill的不同重载版本可以拥有更多的控制权。

2.3.3.1      指定DataTable

有两个Fill重载版本可以指定DataTable(这使你更灵活的控制DataTable

2.3.3.1.1          填充时指定表名称

DataAdapter.Fill(DataSet,”MyTableName”)

2.3.3.1.2          填充时指派DataTable对象(而非DataSet

DataAdapter.Fill(DataTable)

2.3.3.2      根据DataAdapter对象的Fill方法分页

Fill的一个重载版本可以获取查询结果的一部分(实现一部分分页的效果)

DataAdapter.Fill(DataSet,intStartRec,intRecCount,”Table Name”)

但是,你要牢记一点,即使你指定返回的是一部分结果,Fill方法还是将所以查询结果都返回,只不过将不需要的删去了。

所以,Fill方法简化查询分页的效率很一般。

2.3.3.3      DataAdapter对象将一个Recordset的内容填充到DataSet对象

OLEDB.NET数据提供者的两个Fill重载版本,可以将数据从ADO Recordset复制到ADO.NETDataSet

2.3.3.3.1          OleDbAdapter.Fill(DataSet,AdoRecordset,”Table Name”)

2.3.3.3.2          OleDbAdapter.Fill(DataTable,AdoRecordset)

2.3.4            开放和关闭连接

n         DataAdapter对象和Command对象处理Connection对象的方法存在差异。

Command对象需要一个开放的Connection对象,否则Command会有异常。

DataAdapter对象没有这个限制。

调用DataAdapter.Fill方法(SelectCommandConnection是关闭状态),DataAdapter会先开放连接,然后提交查询、取结果,最后关闭连接。

有时候,连续的使用DataAdapterFill方法,会使Connection对象连续的开放和关闭。怎么办?你可以给多个DataAdapter对象指定同一个Connection对象,并且在使用Fill方法之前,就用Connection.Open方法打开连接。

2.3.5            多次调用Fill方法

想一想:如何刷新DataSet中的数据,以便使用户能看到即时的更改。

最简单的办法就是清空DataSet或者DataTable,然后再次调用DataAdapterFill填充。

假使没有清空就连续调用(两次)Fill方法,那么你会在DataSetDataTable中看到多个(两个)客户记录

对代码段来说,DataAdapter不能知道哪些客户是重复的。

通常,数据库的表中会定义一个主键。这样,能防止用户创建重复的行。

DataTable对象也有一个PrimaryKey属性。如果DataAdapter所填充的DataTable有一个主键,那么DataAdapter就会利用该主键来确定哪些行是重复的。(因此,在第一次填充后定义了DataTable的主键,那么第二次的填充DataAdapter会定位重复的行,删去旧值。)

下面假设第一次填充时,有一个客户记录被添加到DataTable中,之后,该客户记录被从数据库中删除了;此时如果进行第二次填充,客户记录会更新吗?不会,DataAdpater在查询结果中找不到该客户的信息,而且也不会将它从DataTable中删除。

想一想:怎么刷新全部数据?要先清空DataSetDataTable,然后再次调用DataAdapter.Fill方法。(这样能确保没有重复行,同时确保数据库中没有的行不添加进DataSet

2.4         将查询结果映射到DataSet

使用DataAdapter对象的TableMappings集合

2.4.1            DataAdapter对象的TableMappings集合

TableMappings集合用来控制DataAdapterDataSet映射到数据库的方式

填充时,将TableMappings保留为空,调用Fill,然后将DataSet作为参数传递,且不指定表名称,DataAdapter会假定你要处理的是(名为Table)的DataTable

TableMappings属性返回一个类型为DataTableMappingCollection的对象。该对象内含多个DataTableMapping对象。可以如下添加:

DataAdapter.TableMappings.Add(“Table”,”Employees”) 告知DataAdapter与名为EmployeesDataTable通讯

创建表映射之后,下一步可以创建列映射。例如:

Dim da as OleDbDataAdapter

Dim tblMap as DataTableMapping

Dim colMap as DataColumnMapping

tblMap=da.TableMappings.Add(“Table”,”Employees”)

colMap=tblMap.ColumnMappings.Add(“EmpID”,”EmployeeID”)

colMap=tblMap.ColumnMappings.Add(“Lname”,”LastName”)

colMap=tblMap.ColumnMappings.Add(“Fname”,”FirstName”)

2.4.2            MissingMappingAction属性

绝大多数情况下,开发人员在DataSet中都会使用与数据库中表相同的列名称。

DataAdapter检查查询结果时,若发现某一列在其映射集合中不存在,它会检查MissingMappingAction属性以确定如何处理这些列。

MissingMappingAction属性接受System.Data名称空间中MissingMappingAction枚举类型的值。

默认值为Passthrough,表示DataAdapter将缺失的列映射为DataSet中同名的列;

Ignore,表示忽略缺失的列;

Error,表示若有缺失列时,会产生异常。

2.5         处理批查询

MS-Sql Server允许执行批查询。

Select CustomerID,CompanyName,ContactName,Phone from Customers where CustomerID=”ALFKI”

Select OrderID,CustomerID,EmployeeID,OrderDate from Orders where Customer=”ALFKI”

如果使用DataAdapter.Fill(DataSet)的方式取得DataSet,将会在DataSet中产生两个DataTable对象。每个DataTable保存一个查询的结果。一个名叫“Table”,一个名叫“Table1

2.6         从存储过程中获取行

假设是Sql Server的存储过程(它能返回结果集)如下:

Create procedure GetAllCustomers as

       Select CustomerID,CompanyName,ContactName,Phone from Customers

Return

使用DataAdapter允许它并取得结果集放入DataSetDataTable中。你可以使用下面的查询语句(两个)之一:

{CALL GetAllCustomers}EXEC GetAllCustomers

另外,如果需要使用Command对象的CommandType属性作为DataAdapterSelectCommand的话,还可以有更多的控制功能。

对于Oracle的存储过程,它不能从查询中返回行,仅能通过输出参数返回数据。

OracleOLEDB提供者和OracleODBC驱动程序允许开发者调用Oracle的存储过程,并通过输出参数取得查询结果。)

因此,Oracle的查询语法如下:

{CALL PackageName.ProcName (?, {resultset 20, OutParam1, OutParam2, …})}

2.7         获取架构信息

设计DataTable的目的在于加强数据上的约束,比如主键、字符串字段最大长度以及可空性限制等。

多数情况下,开发者不需要这些信息,DataAdapter能通过一些关键属性取得架构信息­——比如MissingSchemaAction属性和FillSchema方法

2.7.1            MissingSchemaAction属性

Fill方法使用的是不包含架构信息的DataSet对象和DataTable对象。

默认情况下,DataSetDataTable没有那些列,DataAdapter会添加列信息来存储查询结果,这个操作就是有MissingSchemaAction来管理的。

MissingSchemaAction属性接受System.Data.MissingSchemaAction枚举类型的值。

默认值Add

可能值Ignore,表示忽略缺失列

可能值Error,表示有缺失列就产生异常。

可能值AddWithKey,表示有缺失列时,会在DataSet中添加缺失列,并且,设置MissingSchemaAction属性的两个附加属性:MaxLengthAllowDBNull。如果DataTable不存在或者DataTable不包含任何列,还会导致DataAdapter向数据库查找有关的主键信息。

2.7.2            FillSchema方法

此方法将架构信息存入DataSetDataTable.

此方法可以使用的参数:DataSetDataTableDataSet,表名称。

另外一个需要的参数是:SchemaType类型的值,取值MappedSource。(其中Mapped值将使DataAdapter使用TableMappings表映射的设置来应用返回列;而Source值则让DataAdapter使用查询结果来应用返回列)

另外,FillSchema方法会给返回列设置自增量(AutoIncrement)、允许空(AllowDBNull)、最大长度(MaxLength)等属性。

如果数据库中某列或某组列表示主键(或唯一键),FillSchema方法还要在结果DataTable上创建主键。

posted @ 2008-09-27 08:05  怒杀神  阅读(1174)  评论(0编辑  收藏  举报