透过vs.net数据窗体向导看Ado.net

一个Categories表作为父表,Products表作为子表,CategoryID为外键,建立的数据表关系。

 

 

 

通过加载按钮数据库中的相关数据会被填充到数据集。执行的LoadDataSet()方法的过程如下:

 

 

 

使用DataAdatpter.Fill()方法填充数据到临时的一个数据集,如果操作成功,将合并这个临时数据集到原有的数据集,DataGrid通过表关系绑定子表。

 

 

 

// 尝试填充临时数据集。

 

 

 

this.FillDataSet(objDataSetTemp);

 

 

 

grdProducts.DataSource = null;

 

 

 

// 清空数据集中的旧记录。

 

 

 

objMyDataSet.Clear();

 

 

 

// 将记录合并到主数据集中。

 

 

 

objMyDataSet.Merge(objDataSetTemp);

 

 

 

grdProducts.SetDataBinding(objMyDataSet, "Categories.CategoryProductRel");

 

 

 

在数据填充的方法中我们注意到

 

 

 

dataSet.EnforceConstraints = false;

 

 

 

这一步会对数据填充效率会有所提高。

另外还有一个细节就是执行两个以上DataAdapter的数据访问方法时显式打开关闭数据连接效率会比较高。因为在执行DataAdapter的数据更新方法前和方法后数据连接Connection实例的状态不会改变。如果下面代码。

 

 

 

//this.oleDbConnection1.Open();

 

 

 

this.oleDbDataAdapter1.Fill(dataSet);

 

 

 

this.oleDbDataAdapter2.Fill(dataSet);

执行之前Connection的状态是关闭的,那可想而知这一过程会执行两次打开连接关闭连接。

 

 

 

其实一次就够。

 

 

 

为了数据的严密性,填充完数据后不要忘了加上下面代码,

 

 

 

// 重新打开约束检查。

 

 

 

dataSet.EnforceConstraints = true;

 

 

 

如果是直读那就无所谓了。

 

 

 

有了数据填充那就来看数据的单值绑定和多值绑定。

 

 

 


 


 


 


三.数据绑定

 

 

 

数据的单值绑定如下:

 

 

 

this.editCategoryID.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.objMyDataSet, "Categories.CategoryID"));

 

 

 

this.editCategoryName.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.objMyDataSet, "Categories.CategoryName"));

 

 

 

上面一段代码把数据表的列绑定到了TextBox的Text属性上。

 

 

 

数据的多值绑定如下:

 

 

 

grdProducts.SetDataBinding(objMyDataSet, "Categories.CategoryProductRel");

 

 

 

可见通过关系绑定数据相当方便。

 

 

 


 


 


 


四.数据浏览

 

 

 

这里通过BindingContext对象的索引得到BindingManagerBase实例,而BindingManagerBase.Position就是我们需要的,通过Position来显示某一行的数据记录。

 

 

 

例如下一条:

 

 

 

this.BindingContext[objMyDataSet,"Categories"].Position = (this.BindingContext[objMyDataSet,"Categories"].Position + 1);

 

 

 

最后一条:

 

 

 

this.BindingContext[objMyDataSet,"Categories"].Position = (this.objMyDataSet.Tables["Categories"].Rows.Count - 1);

 

 

 

另外调用PositionChanged()方法来改变导航按钮之间的索引显示。

 

 

 


 


 


 


五.数据编辑

 

 

 

从添加方法中我们可以看到下面代码:

 

 

 

// 清除当前编辑内容

 

 

 

this.BindingContext[objMyDataSet,"Categories"].EndCurrentEdit();

 

 

 

经常有人在csdn上提问为什么在编辑DataGrid或TextBox的时候,只有当编辑框失去焦点的时候才会被保存。要实现不改变焦点就保存可以通过上面代码实现。

 

 

 

相对应的取消如下:

 

 

 

this.BindingContext[objMyDataSet,"Categories"].CancelCurrentEdit();

 

 

 

删除数据的代码如下:

 

 

 

this.BindingContext[objMyDataSet,"Categories"].RemoveAt(this.BindingContext[objMyDataSet,"Categories"].Position);

 

 

 

看到上面代码发现原来数据不是真正的在数据源删除,不过我们开发的时候可能用的更多的是DataRow的Delete()方法,这样能够提交数据更新到数据源。

 

 

 


 


 


 


六.数据更新

 

 

 

向导生成的代码如下:

 

 

 

public void UpdateDataSet()

 

 

 

{

 

 

 

     // 创建一个新数据集来保存对主数据集所做的更改。

 

 

 

     WindowsApplication1.MyDataSet objDataSetChanges = new WindowsApplication1.MyDataSet();

 

 

 

     // 停止当前的任何编辑。

 

 

 

     this.BindingContext[objMyDataSet,"Categories"].EndCurrentEdit();

 

 

 

     this.BindingContext[objMyDataSet,"Products"].EndCurrentEdit();

 

 

 

     // 获取对主数据集所做的更改。

 

 

 

     objDataSetChanges = ((WindowsApplication1.MyDataSet)(objMyDataSet.GetChanges()));

 

 

 

     // 检查是否做了任何更改。

 

 

 

     if ((objDataSetChanges != null))

 

 

 

     {

 

 

 

         try

 

 

 

         {

 

 

 

              // 需要做一些更改,所以尝试通过调用 update 方法

 

 

 

              // 和传递数据集以及任何参数来更新数据源。

 

 

 

              this.UpdateDataSource(objDataSetChanges);

 

 

 

              objMyDataSet.Merge(objDataSetChanges);

 

 

 

              objMyDataSet.AcceptChanges();

 

 

 

         }

 

 

 

         catch (System.Exception eUpdate)

 

 

 

         {

 

 

 

              // 在此处添加错误处理代码。

 

 

 

              throw eUpdate;

 

 

 

         }

 

 

 

         // 添加代码以检查返回的数据集中是否有任何可能已被

 

 

 

         // 推入到行对象错误中的错误。

 

 

 

     }

 

 

 

}

 

 

 

更新过程很经典,通过获取修改过的数据集更新子集提交到数据源完成更新动作,接着合并子集到原有数据集,顺便提一下,合并的过程是基于数据表主键来判断的。通过调用DataSet.AcceptChanges()方法提交自加载此 DataSet 或上次调用 AcceptChanges 以来对 DataSet 进行的所有更改。对应的就是Data.RejectChanges();回滚自创建 DataSet 以来或上次调用 DataSet.AcceptChanges 以来对 DataSet 进行的所有更改。

 

 

 


 


 


 


七.补充

 

 

 

对于数据的更新需要视程序环境而定,不能都通过获取子集再合并的方法,具体请看ADO.NET中的多数据表操作浅析—修改一文。也有人问起怎样实现这样的功能:在数据库中的某一个字段数据为0或1,而在程序显示上想让它显示为是或否,这里我认为最好不要在Sql语句上做文章,代替的方法就是使用Binding对象的Format 事件和Parse事件。Binding.Format 事件,当将某控件的属性绑定到某个数据值时发生。Binding.Parse 事件,在数据绑定控件的值更改时发生。还有可以通过BindingManagerBase.PositionChanged事件来设置各个按钮的状态。需要具体的例子可以看MSDN或《Ado.net Core Reference》一书。另外,使用Try{}catch (System.Exception ex){}还是要视情况而定,不能一味的全都通过Exception基类把什么都扑捉了,如果知道有可能会抛出什么类型的异常,还是越具体越好,造成的反面效果就是要写更多的代码。具体为什么要这么做可以看《Applied Microsoft.NET Framework Programming》一书。

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值