* 摘要
。数据适配器概述
。数据适配器的创建
。数据适配器的属性
。数据适配器的方法
。数据适配器的事件
。使用数据适配器最佳实践
* 数据适配器概述
。DataAdapter连接到数据库以填充DataSet的对象。然后,它又连接回数据库,根据DataSet保留数据时所执行的操作来更新数据库中的该数据。
。DataAdapter:它起着桥梁的作用,在DataSet和其源数据存诸区之间进行数据检索和保存。
。DataAdapter对象可以隐藏和Connection,Command对象沟通的细节,通过DataAdapter对象建立,初始化DataTabel,从而和DataSet对象结合起来在内存存放数据表副本,实现离线式数据库操作。
* 数据适配器
。数据源和数据集之间的桥梁
。包括:
-OleDbDataAdapter
-SqlDataAdapter
-......
* 数据适配器的创建
。设计时创建
-利用“服务器资源管理器”:
选择SQL Northwind连接,把Categories表添加到窗体上,命名为daCategories
-使用工具箱
添加适配器,命名为daProducts
。运行时创建
-命名为daSupplies
* 数据适配器的属性
。数据源更新
-InsertCommand
-SelectCommand
-DeleteCommand
-UpdateCommand
。TableMappings:用于维持数据集中的列和数据源中列的关系
。AcceptChangesDuringFill:决定AcceptChanges方法是否被添加到数据集中的每一行所调用,默认为true
* Command对象
。SelectCommand:用来获取数据源中的记录;
。InsertCommand:用来向数据源中新插入一条记录;
。UpdateCommand:用来更新数据源中的数据;
。DeleteCommand:用来删除数据源中的记录。
* TableMappings集合
。数据集和数据源的桥梁:
-数据集并不清除它所包含的数据从哪里来,而Connection也不知道它所检索的数据都发生了什么改变。
-数据适配器用于维持这两者之间的联系,它通过TableMappings集合来实现这一目标。
。包括
-DataTableMappings
-DataColumnMappings
。SourceColumn
。DataSetColumn
* 生成数据集和绑定数据
。生成数据集
-选择适配器
-选择“生成数据集”
-修改数据集名称
。绑定数据
-选择适配器的DataSource属性
* DataSet版本
。DataSet中,可以存在同一个DataRow的多个版本。它们由DataRowVersion枚举来指定。
-Current该行中包含当前值。
-Default根据当前DataRowState,为默认行版本。
-Original该行中包含其原始值。
-Proposed该行中包含建议值。
* DataRowVersion
版本在以下情况下发生更改
。在调用DataRow对象的BeginEdit方法之后,如果更改该值,则Current和Proposed值变得可用。
。在调用DataRow对象的CancelEdit方法之后,Proposed值将被删除。
。在调用DataRow对象的EndEdit方法之后,Proposed值变成Currnt值。
。在调用DataRow对象的AcceptChanges方法之后,Original值变得与Current值相同。
。在调用DataTable对象的AcceptChanges方法之后,Original值变得与Current值相同。
。在调用DataRow对象的RejectChanges之后,Proposed值将被丢弃,版本变成Current.
* 数据适配器的方法
。FIll:把数据从数据源加载到数据集中。
。Update:把数据从数据集加载到数据源中。
* FILL方法
。Fill(DateSet):用数据源返回的行填充指定数据集
。Fill(DataTable):
。Fill(DataSet,tableName):在指定的数据集中,用数据源返回的行填充名称为tableName的数据表。
。Fill(DataTable,DataReader):用指定的DataReader填充数据表。
* Fill方法的使用
。默认情况下,在使用DataAdapter的Fill方法时,除了会填充DataSet之外,还会自动调用DataSet.AcceptChanges.调用后所有行状态中没有任何行是“新改变的”。
。对于某些情况,如希望从多个数据源填充一个DataSet,再将其写回另外一个数据存储,这时要把DataAdapter的属性
AcceptChangesDuringFill设置为false,以便让结果行表现为新添加的行。
* Update方法
。Update(DataSet):根据指定的数据集中的数据表更新数据
。Update(DataRows):根据指定的数据行数组更新数据源
。Update(DataTable):根据指定的数据表更新数据源
* Update方法
。当调用Update方法时,DataAdapter将分析己作出的更改并执行相应的命令(Insert,Update或Delete)。当DataAdapter遇到对DataRow的更改时,它将使用InsertCommand,UpdateCommand或DeleteCommand来处理该更改。这样,您就可以通过在设计时指定命令语法并在可能时通过使用存储过程来尽量提高ADO.NET应用程序的性能。
。在调用Update之前,必须显式设置这些命令。如果调用了Update但不存在用于特定更新的相应命令(例如,不存在用于已删除行的
DeleteCommand),则将引发异常。
* CommandBuilder
。如果DataTable映射到单个数据库或从单个数据库表生成,则可以利用CommandBuilder对象自动生成DataAdapter的
DeleteCommand,InsertCommand和UpdateCommand。
。为了生成Insert,Update或Delete语句,CommandBuilder会自动使用SelectCommand属性来检索所需的元数据集。
* 数据适配器的事件
。OnRowUpdating:在数据行更新前执行。
。OnRowUpdated:在数据行更新后执行。
其最佳用法是检查单条更新语句的执行结果。
* SqlRowUpdatedEventArgs属性
Command:要执行的数据命令
Errors:错误
Row:要更新的行
StatementType:要执行的命令类型,可能为Select,Insert,Delete和Update
RecordsAffected:要影响的行数
TableMapping:更新所使用的DataTableMapping
* 使用数据适配器最佳实践
。使用多个表填充一个DataSet
。避免自动增量值冲突
。CommandBuilder的使用
* 使用多个表填充一个DataSet
。如果你是用批处理从多个表返回数据并把这些数据填充到一个DataSet,fill方法将会使用第一个表的表名命名第一个表,以后的表命名将会采用在第一个表的表名基础上加上一个递增的数字。
。SqlDataAdapter da=new SqlDataAdapter("select * from customers;select * from orders;",myConnection);
。da.TableMappings.Add("Customers1","Orders");
。DataSet ds=new DataSet();
。da.Fill(ds,"Customers");
* 避免自动增量值冲突
。DataSe使您可标识那些添加新行时自动对其值进行递增的列。在DataSet中使用自动增量的列时,如果自动增量的列来自数据源,可避免添加到DataSet的行和添加到数据源的行之间本地编号冲突。
。例如一个表,它的主键列CustomerID是自动增量的。两个新的客户信息行添加到表中,并接收到自动增量的CustomerID值1和2。然后,只有第二个客户行被传递给DataAdapter的方法Update,新添加的行在数据源接收到一个自动增量的CustomerID值1,与DataSet中的值2不匹配。当DataAdapter用返回值填充表中第二行时,就会出现约束冲突,因为第一个客户行已经使用了CustomerID值1。
。要避免这种情况,建议把DataSet中的列创建为AutoIncrementStep值等于-1并且AutoIncremerntStep值等于0,另外,还要确保数据源生成的自动增量标识值从1开始,并且以正阶值递增。
* CommandBuilder的使用
。在设计阶段不要使用CommandBuilder,否者产生DataAdapter Command属性的进程将会受到干扰。
。CommandBuilder使用SelectCommand决定其他Command属性的值。如果DataAdapter的SelectCommand本身发生变化,应该使用RefreshSchema去刷新Command的属性。
。只要DataAdapter的Command属性为空,CommandBuilder就仅仅创建一个Command,即使你明确地指定Command的属性值,CommandBuilder也不会重写,所以如果你想创建一个Command并保留以前的属性设置,那么就把Command的属性设置为null.