导航
  • 主页
  • C#综合技术
  • C#互联网桌面应用
  • AppLauncher
  • WinForm
  • WPF
  • 问答

Vs2005中更新父子表标识列的问题

quou2002 2006-08-15 05:16:49
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吧,可是那么多列啊,当作参数可真麻烦,再郁闷,居然还是可空类型的。。。
...全文
183 点赞 收藏 12
写回复
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
addwing 2006-09-04
关注,帮你顶!
回复
ok757 2006-09-03
up
回复
quou2002 2006-08-17
up
回复
quou2002 2006-08-17
up
回复
quou2002 2006-08-16
up
回复
Knight94 2006-08-15
to 像你说的,把主子表内容一起插入,就违背了它的这个‘新’绑定模型。实现应该不难(可是我的这2个表实际各有十几列,按以往的方法,代码量也不小),可是并不是我想要的。

你的问题关键就是在与DataAdapter来批量更新DataSet数据的时候,要在插入主表的时候,能获得新产生的ID。

但是就目前ADO.net来说,虽说可以在一个command中可以做多种不同操作,但是在da下的command中,进行批量更新或者插入的时候,无法对每个command来做两个以上的操作,也就是在用InsertCommand执行插入的同时,无法去获得新的ID来更新datarow某个字段。

如果这一点没法在DA实现,你的问题也就无法实现。
回复
Knight94 2006-08-15
对于你所说的05新绑定,其实在03中就可以,只要增加DataSet.Relations即可
回复
quou2002 2006-08-15
to Knight94(愚翁)
为了最大限度的利用类型化数据集和Vs2005里的新的数据绑定模型,我才这样做的。像这种级联插入,更新的问题,即使是在1.1时代,自己写几个存储过程,一步步的来也不是很难的事情。
现在的‘数据绑定’为我们封装了很多,你看,如果不是这个问题,这个级联增删查改所实现的功能,实际我更改的代码很少,配置也不多,很适合某些需求场合的快速开发,降低成本。

像你说的,把主子表内容一起插入,就违背了它的这个‘新’绑定模型。实现应该不难(可是我的这2个表实际各有十几列,按以往的方法,代码量也不小),可是并不是我想要的。
回复
Knight94 2006-08-15
to 问题来了:insert单条记录时,首先插入新的depart表数据,完成后,数据库新产生的标识值departId并没有‘传’给紧接下来欲插入 person表的语句中。即,此时插入person表的新纪录中的departId值仍旧是DataTable的标识列值,而不是实际数据库所需的标识值。数据库此时会因为外键约束导致插入失败。

对于这种问题,你应该在插入的时候,如果避免在操作上的麻烦,应该采用存储,把主子表的内容一起进行插入,在存储中做细节处理。
回复
Knight94 2006-08-15
这是肯定的,因为DataTable并没有觉得应该在插入的时候需要去查询获得新的ID。
回复
iflang 2006-08-15
顶一下,,,再看
回复
geoffe 2006-08-15
没有这么做过
如果要插入一个表
把另一个清除了再说
如果要用就让它读一次
或者及时更新
回复
发动态
发帖子
C#
创建于2007-09-28

10.4w+

社区成员

.NET技术 C#
申请成为版主
社区公告

全世界最好的语言,没有之一.