DataSet允许包含多个DataTable,而且这些DataTable可以存在父子关系。
问题描述:假设现在有2个表,部门(depart),员工(person)。
depart表结构如下:
        ┌──────┬─────┬─────┐
      ◆│departId    │int       │标识列    │←┐
        ├──────┼─────┼─────┤  │主
        │departName  │nvarchar  │          │  │外
        ├──────┼─────┼─────┤  │键
        │....        │          │          │  │
        └──────┴─────┴─────┘  │
person表结构如下:                                │
        ┌──────┬─────┬─────┐  │
      ◆│personId    │int       │标识列    │  │
        ├──────┼─────┼─────┤  │
        │personName  │nvarchar  │          │  │
        ├──────┼─────┼─────┤  │
      ◇│departId    │int       │          │←┘
        └──────┴─────┴─────┘
---------------------------------------------------------
当我通过Vs2005的数据源设计器,把上述2个表加入后,IDE智能地通过读数据库信息正确的恢复了2表之间的关系(主外键关系),至此我可以使用类型化数据集了。新的DataSet里现在有了2个DataTable,分别对应数据库里的depart和person表。在这2个DataTable的相关属性里,我们可以看见设计器已自动识别并对departId列和personId列指明了‘标识列’属性。
┌────────────────┐
│这里说明一点的是:DataTable的标 │       
│  识列的具体值和实际数据库标识列│         
│  的值并没有联系。              │ 
└────────────────┘ 
UI界面的设计:直接通过拖动数据源列表里相关表(关联的2个表),得到2个具有及联效果的dataGridView,通过在导航栏的Save按钮事件里稍作处理,即把2个表的update按主、子的顺序写好。至此涉及2个表的增删查改均完成。
=====================
问题来了:insert单条记录时,首先插入新的depart表数据,完成后,数据库新产生的标识值departId并没有‘传’给紧接下来欲插入person表的语句中。即,此时插入person表的新纪录中的departId值仍旧是DataTable的标识列值,而不是实际数据库所需的标识值。数据库此时会因为外键约束导致插入失败。这种插入失败尤其在以下情况表现明显:例如,depart表中50条记录,在数据库里删除后面40条,则剩下编号为1~10的10条记录,这时标识列的下一个值应该是51。如果你此时运行上述程序,那么DataTable为其产生的下一个departId则为11,相应的person这个DataTable里的departId也为11。那么执行插入操作时,depart表记录正确插入(毕竟它知道标识列不用真正赋值),可是插入person表时,departId赋值为11可就报错了。我尝试把depart表的insert写成存储过程,并out新生成的标识值,然后将这个参数属性定为output和DataTable里的departId列绑定。希望在我insert主表后,回传的值立刻更新子表departId,可是依旧不行。-------我认为微软应该考虑到这个‘基本’需求的问题,也许是我哪里出错吧。---------
不行的话,我只有通过DataTable的GetChanges分离出insert,单独控制这些插入了。可是类型化数据集,它把insertCommand等都封装了,不能直接改参数值,郁闷,就用那个暴露的insert吧,可是那么多列啊,当作参数可真麻烦,再郁闷,居然还是可空类型的

解决方案 »

  1.   

    这是肯定的,因为DataTable并没有觉得应该在插入的时候需要去查询获得新的ID。
      

  2.   

    to 问题来了:insert单条记录时,首先插入新的depart表数据,完成后,数据库新产生的标识值departId并没有‘传’给紧接下来欲插入 person表的语句中。即,此时插入person表的新纪录中的departId值仍旧是DataTable的标识列值,而不是实际数据库所需的标识值。数据库此时会因为外键约束导致插入失败。对于这种问题,你应该在插入的时候,如果避免在操作上的麻烦,应该采用存储,把主子表的内容一起进行插入,在存储中做细节处理。
      

  3.   

    to Knight94(愚翁) 
    为了最大限度的利用类型化数据集和Vs2005里的新的数据绑定模型,我才这样做的。像这种级联插入,更新的问题,即使是在1.1时代,自己写几个存储过程,一步步的来也不是很难的事情。
    现在的‘数据绑定’为我们封装了很多,你看,如果不是这个问题,这个级联增删查改所实现的功能,实际我更改的代码很少,配置也不多,很适合某些需求场合的快速开发,降低成本。像你说的,把主子表内容一起插入,就违背了它的这个‘新’绑定模型。实现应该不难(可是我的这2个表实际各有十几列,按以往的方法,代码量也不小),可是并不是我想要的。
      

  4.   

    对于你所说的05新绑定,其实在03中就可以,只要增加DataSet.Relations即可
      

  5.   

    to 像你说的,把主子表内容一起插入,就违背了它的这个‘新’绑定模型。实现应该不难(可是我的这2个表实际各有十几列,按以往的方法,代码量也不小),可是并不是我想要的。你的问题关键就是在与DataAdapter来批量更新DataSet数据的时候,要在插入主表的时候,能获得新产生的ID。但是就目前ADO.net来说,虽说可以在一个command中可以做多种不同操作,但是在da下的command中,进行批量更新或者插入的时候,无法对每个command来做两个以上的操作,也就是在用InsertCommand执行插入的同时,无法去获得新的ID来更新datarow某个字段。如果这一点没法在DA实现,你的问题也就无法实现。