1. 配置 DataAdapter 以检索信息
1.1. DataAdapter
• 数据适配器是数据集与数据源交互的桥梁
–使相当于数据源本地拷贝的数据集可以与数据源之间进行交互。 • 为数据库提供的主要两种数据适配器 – SqlDataAdapter:不经过OLEDB层直接与SQLServer交互,速度较OleDbDataAdapter快。 – OleDbDataAdapter:适用于任何可以用OLEDB数据提供者访问的数据源。1.2. XxxDataAdapter对象模型
• Command 对象
– 通过数据适配器来读取数据源信息的命令对象,并将其保存在数据适配器的SelectCommand属性中。 – 通过数据适配器可以将数据集中的改变提交到数据源的Command对象中,并保存在数据适配器的InsertCommand、UpdateCommand和DeleteCommand属性中。 • DataTableMapping(数据表映射)集合 – DataTableMapping集合保存了数据集中的表、字段与数据库中的表、字段的映射关系。• 数据适配器的属性
– SelectCommand 从数据源中读取数据 – InsertCommand 将数据由数据集插入数据源 – UpdateCommand 将数据集中更新的行写回数据源 – DeleteCommand 在数据源中删除数据 • 数据适配器的方法 – Fill() 使用由SelectCommand属性指定的Select语句从数据源中读取/更新数据到数据集。 – Update() 对数据集DataTable对象中特定的行调用执行Insert、Delete、Update操作的对应的命令对象。1.3. 创建使用新SELECT 语句的DataAdapter
• 创建一个执行SELECT语句的数据适配器 –对非连接方式应用以只读方式访问数据。 • 在定义数据适配器时必须指定 –一个用于查询的SELECT语句 – 一个新的或者已经存在的数据库连接1.4. 创建使用现有存储过程的 DataAdapter
• 可以编程创建一个执行存储过程 –为SelectCommand指定一个存储过程。 – 如果需要可以为InsertCommand、UpdateCommand和DeleteCommond指定存储过程。 • 必须指定 – 一个新的或者已经存在的数据库连接 – 调用的存储过程2. 使用 DataAdapter 填充 DataSet
2.1. 使用 DataAdapter 填充 DataSet
• 可以使用数据适配器来填充数据集
–调用数据适配器的Fill()方法。 • Fill()方法执行SelectCommand –使用查询结果的内容和结构填充数据集中的数据表。 • 可以通过下列方法提高性能 – DataSet.EnforceConstraints=False。 – 对DataTable 对象调用BeginLoadData()方法。2.2. 高效地填充 Dataset
• 在填充一个数据集前显式地定义数据结构 – 数据表、数据列以及数据关联在数据被载入前已经确定。 – 使数据可以被更高效地载入。 • 如何显式地定义一个数据集的数据结构 – 创建一个类型化的数据集类dsCustomers.Customers.BeginLoadData();daCustomers.Fill(dsCustomers.Customers);dsCustomers.Customers.EndLoadData();DataGrid1.DataSource = dsCustomers.Customers.DefaultView; – 或者以编程的方式创建数据表、数据列和数据关联等。2.3. 为 DataSet 指定附加约束
• 可以在数据结构未知的情况下填充数据集 – 数据集的数据结构在设计阶段未知。 – 在运行时根据得到的数据来确定数据集的数据结构。 – 可以在运行时通过数据适配器控制如何创建并生成数据集的数据结构。 • 使用MissingSchemaAction属性控制数据结构生成 • 调用FillSchema()方法建立一个新的数据集的数据结构2.4. 使用多个DataAdapter 填充一个DataSet
• 可以使用多个数据适配器填充一个数据集 –每个数据适配器填充数据集中一个独立的表。 • 为每一个数据适配器调用Fill()方法 –在数据集中指定填充哪一个表daCustomers.Fill(dsCustomerOrders.Customers);daOrders.Fill(dsCustomerOrders.Orders);DataGrid1.DataSource =dsCustomerOrders.Customers;3. 配置DataAdapter 更新后台数据源
3.1. DataSet 跟踪更改的方式
• 每个数据行对象都有一个RowState属性
– 标识数据集中每一行数据的状态。 – 状态的类型 • DataRowState.Added 该行已经插入到数据集 • DataRowState.Deleted 该行已经从数据集中删除 • DataRowState.Detached 该行已经创建,但未增加到数据集中的DataRowCollection • DataRowState.Modified 该行已经更改 • DataRowState.Unchanged 该行没有发生任何变化• 每个数据集都对每一行数据维护两份拷贝
–当前版本 DataRowVersion.Currentif (row.RowState == DataRowState.Added)row[“FieldName",DataRowVersion.Current] – 原始版本DataRowVersion.Originalif (row.RowState == DataRowState.Deleted)row[“FieldName",DataRowVersion.Original]3.2. 数据更新命令
• 一个SqlDataAdapter或OleDbDataAdapter对象都有一些命令对象可以用来更改数据源的数据 – InsertCommand – UpdateCommand – DeleteCommand • 语法:对Sql和OleDb的数据适配器以及各个命令对象完全相同 – public SqlCommand InsertCommand {get; set;} 3.3. 使用 CommandBuilder 生成命令• InsertCommand
– 在数据源处为表中所有RowState 为Added 的行插入一行。插入所有可更新列的值(但是不包括标识、表达式或时间戳等列)。 • UpdateCommand – 在数据源处更新表中所有 RowState 为 Modified 的行。 更新所有列的值,不可更新的列除外,例如标识列或表达式列。 – 更新符合以下条件的所有行:数据源中的列值匹配行的主键列值,并且数据源中的剩余列匹配行的原始值。 有关更多信息,请参见本主题后面的“更新和删除的开放式并发模型”。 • DeleteCommand – 在数据源处删除表中所有RowState 为Deleted 的行。删除符合以下条件的所有行:列值匹配行的主键列值,并且数据源中的剩余列匹配行的原始值。4. 将数据更改保存到数据源
4.1. 使用DataSet对象的GetChanges方法的时机
• 当需要将数据更改传给由另一个对象使用的另一个类的时候调用GetChanges()方法If dsCustomers.HasChanges(DataRowState.Modified) ThenDim dsTemp As DataSetdsTemp = dsCustomers.GetChanges(DataRowState.Modified)DataGrid1.DataSource = dsTemp.Tables(0).DefaultViewEnd If
• 使用GetChanges()方法得到包含该数据集中所有数据更改的数据集的拷贝
– 从数据被载入开始。
– 从AcceptChanges()方法最后一次被调用开始。4.2. 将更改合并到一个DataSet对象
• 使用Merge()方法合并两个数据集:一个原始数据集以及一个仅包含对原始数据集更改的数据集aDataSet.Merge(anotherDataSet) • 被合并的两个数据集要有相同的数据结构4.3. 使用DataSet更新数据源
• 数据适配器的Update()方法对指定的数据表中被更新过的每一行调用适当的SQL语句 – INSERT – UPDATE – DELETE • 代码示例aDataAdapter.Update(aDataSet, aDataTable)4.4. DataSet接受数据更改的方式
• 数据集的AcceptChanges()方法提交自数据被载入或自此次调用起所有该数据集的数据更改 • 可以对整个数据集调用AcceptChanges()方法,或者对一个DataTable 对象的一个数据行对象调用5. 冲突处理
5.1. 发生冲突
• 非连接环境使用了开放式并发机制 – 在一步数据操作完成后数据库锁立即被释放。 – 非连接环境使用开放式并发机制保证其他资源对数据库的同步访问。 – 保守式并发机制在整个数据操作过程中保持数据库的锁。 • 在更新数据库时会产生数据冲突 – 另一个应用或服务可能已经更改了数据 • 例如 – 删除已经不存在的行 – 更新已经被更新的列5.2. 检测冲突
• 数据适配器配置向导可以产生用来监测冲突的SQL语句 • 当更新数据库时 –数据更新命令比较数据库中的当前数据与原始值。 – 任何不同都会抛出一个冲突。5.3. 解决冲突
• 使用HasErrors属性来测试错误 – DataSet.HasErrors – DataTable.HasErrors – DataRow.HasErrors • 选择下列一种策略解决冲突 – 用数据集中的值覆盖曾经有过的数据操作。 • 适用于管理员系统用来强制将数据覆盖数据源中的数据 – 保持数据集中冲突行以便后续重新更新数据库。 • 将冲突的数据保存在数据集中以便重试 • “使用开放式并发”选项的默认策略• 拒绝冲突的行并在数据集中回滚到初始值
–拒绝在本地数据集中冲突的数据,将数据回滚到从数据库中加载得到的初始值。 –对冲突的数据集、数据表、数据行调用RejectChanges()方法。 • 拒绝冲突的行并从数据库得到最近的数据 – 调用数据集的Clear()方法,重新从数据库中加载数据。