三层中新增数据,自增字段如何处理
在三层中,自增字段(id),在新增完数据后,需要返回id,用delphi的数据感知控件,能实现吗? 问题点数:100、回复次数:58Top
1 楼fox1999(红狐)回复于 2006-10-13 14:21:01 得分 0
好象不行.
用 GUID 做主键Top
2 楼do2008(aiGooo·闲来吹吹牛,不亦乐乎)回复于 2006-10-13 23:42:42 得分 0
在新增完数据后,其实自增字段(id)已经有值了
可以这样写代码,获取了
myid = table.FieldByName('id').AsInteger;
数据感知控件,刷新一下状态,应该也能获取得到了Top
3 楼fox1999(红狐)回复于 2006-10-16 12:56:57 得分 0
楼上的方法有两层时,用 ADO 控件时可行.Top
4 楼ddqqyy(ddqqyy)回复于 2006-10-16 19:50:59 得分 0
如果只是增加一条记录,则不用理会自增字段的值,也不用给它赋值(当它不存在),记录增加到数据库后,数据库会自动给该字段赋值。
如果是多条记录的情况,如使用TClientDataSet控件,先在客户端增加了多条记录之后,再一次性ApplyUpdate更新的情况。
1、定义一个全局Integer变量AutoID,初始值为-1。
2、在TClientDataSet的BeforeInsert事件中,把AutoID值赋给当前记录的自增加字段,然后Dec(AutoID)。
3、在与TClientDataSet相关联的TDataSetProvider.BeforeUpdateRecord事件中编写:
if UpdateKind = ukInsert then
DeltaDS.FieldValues['AutoFieldName'] := Null;
4、TClientDataSet.ApplyUpdates(0);
5、TClientDataSet.Refresh;
6、OK了
编程思路就是上述,取自Borland Developer Network,应该是高手的方法吧。
Top
5 楼cangwu_lee(橙子)回复于 2006-10-20 11:06:04 得分 0
Sql server 自增加字段 和 Oracel 序列,都可以返回最后的值。
找找资料Top
6 楼madyak(无天)回复于 2006-10-20 11:15:02 得分 0
在三层中,如果需要取回新ID,最好是不用自增长类型了。麻烦多多,尤其是在处理主从表时,增加了开发难度。Top
7 楼ysai(所有真的都是假的真,所有假的都是真的假)回复于 2006-10-20 11:20:36 得分 0
我的数据库设计原则:
表不设主键=等死
字段设置默认值(包含自增字段)=找死 (3层用中使用ClientDataset时)Top
8 楼Cassava(车超)回复于 2006-10-22 12:16:18 得分 0
用存储过程实现才是最保险的方法
如:
CREATE PROCEDURE aaa
@AutoID int OutPut
as
inser into a(a)values('a')
set @AutoID=SCOPE_IDENTITY() //请看SCOPE_IDENTITY()的帮助就清楚了,它能解决多用户同时操作而造成不能取得最新的正确id的问题Top
9 楼gogogo(嘿嘿)回复于 2006-10-22 14:06:38 得分 0
这个问题前几天才碰到,一句话,不能使用自增字段,如果你使用ClientDataSet,并且需要用到这个ID的时候,就是不能用,必须重新设计数据库。
参见http://community.csdn.net/Expert/topic/5070/5070916.xml?temp=.4269068Top
10 楼Cassava(车超)回复于 2006-10-22 21:40:08 得分 0
谁说的不能用自增字段
用我上面所说的方法就肯定可以Top
11 楼madyak(无天)回复于 2006-10-30 09:14:30 得分 0
如果实在想用自增ID实现,当然能实现,只是效率不会高,至少网络服务端与客户端,增加了回传ID这一步,增大了网络的开销。在三层中是应该毕免这种情况的Top
12 楼comanche(太可怕)回复于 2006-10-30 09:57:50 得分 0
自增长本来就是 MS sql server 专有的嘛, 其它的用生成器
楼上的 CDS.ApplyUPdate 后 CDS.Refresh 当然就可以用自增长的, 就是最后 Refresh 是不是可以接受的问题
DSP 有 propogateChanges 选项, DSP.ApplyUpdate 的返回值就是所有的在 Before&After Update Record 时的 Field.NewValue(用 CDS 的会自动直接合并), 关键就是取得 autoID 了
个人觉得是没办法, 除非不用 autoID, autoID 的功能实际上很容易仿真, SELECT MAX(ID) FROM TABLE, 不过这样可能在多 CPU 和并发量大的时间产生 key 冲突, 数据是没错, 偶尔一个用户会增加失败
生成器功能也很容易仿真的就是建另一个表作为生成器
CREATE TABLE [KeyValues] (
[Name] [varchar] (20),
[CurrentValue] [int]
) ON [PRIMARY]
CREATE PROCEDURE getid @ID INT OUTPUT, @NAME VARCHAR(20) AS
BEGIN
UPDATE KEYVALUES SET CURRENTVALUE = CURRENTVALUE + 1 WHERE NAME = @NAME
SELECT @ID = CURRENTVALUE FROM KEYVALUES WHERE NAME = @NAME
IF @ID IS NULL SET @ID = -1
END
Top
13 楼comanche(太可怕)回复于 2006-10-30 09:58:42 得分 0
用法自已研究下, 有事不能多说了呵Top
14 楼ddqqyy(ddqqyy)回复于 2006-10-30 10:10:58 得分 0
三层中解决自增ID的方法,早就有范式,也不存在回传ID,增大网络开销的顾虑,看看人家在2002年就提出的解决方法吧:
http://bdn.borland.com/article/20847Top
15 楼madyak(无天)回复于 2006-11-01 08:55:31 得分 0
用AUTOID不方便之处以上好象解决的都不理想,没有解决到关键上。在项目和产品中,经常为了操作方便,主从表同时增加新数据。如果在主表中新增加一些数据,对应这些主表新数据,又新加了一些子记录。由于主表在提交之前,不能确定主键ID。而子表此时又需要引用主表的ID。
这样的问题上面好象都没有解决吧。
虽然能解决,解决方法也不是一种,但这些都增大了网络的开销或增加了开发难度。但根源是一个自动增长带来了。Top
16 楼madyak(无天)回复于 2006-11-01 09:04:02 得分 0
http://bdn.borland.com/article/20847
解决主从表的方法好象有点问题,BeforeUpdateRecord是在一个事务内部执行的,在此得不断的close,open好象不太合适。Top
17 楼Cassava(车超)回复于 2006-11-01 21:52:22 得分 0
回传一个ID也怕增大网络的开销,建议你不做网络程序算了
主从表同时增加的程序我做过,就是使用我上面说的方法的做的,运行的很好,没觉得有什么不托,也没觉得难度有多大
Top
18 楼madyak(无天)回复于 2006-11-02 09:45:32 得分 0
哪个方法?原听其详Top
19 楼Cassava(车超)回复于 2006-11-02 11:01:45 得分 0
CREATE PROCEDURE aaa
@AutoID int OutPut
as
inser into a(a)values('a')
set @AutoID=SCOPE_IDENTITY() //请看SCOPE_IDENTITY()的帮助就清楚了,它能解决多用户同时操作而造成不能取得最新的正确id的问题
Top
20 楼madyak(无天)回复于 2006-11-02 11:19:33 得分 0
哦。还是不明白,主从表是如何实现的。
从表引用主表的ID,是在客户端实现的绑定还是在服务端实现的绑定?Top
21 楼comanche(太可怕)回复于 2006-11-03 10:35:12 得分 0
服务端实现, 然后回送新的 ID, 比方, CDS 中有 id 字段是 key,sql server 去掉自增, 强调不用自增
1.在客户机 CDS.BeforePost 代码中写到, 形式如下
var
XID: Integer; // 定义在之外哈, 这个初值是 0
procedure XXXXXXXXBeforePost(DataSet: TDataSet);
begin
if DataSet.State = dsInsert then
begin
InterlockedDecrement(XID);
DataSet.FieldValues['id'] := XID; 给一个负值在 key 上, 多记录新增不出错(显示上)
end;
end;
2.在服务器的 BeforeUpdateRecord 代码中写到
XXXDSPBeforeUpdateRecord(Sender: TObject; SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind: TUpdateKind; var Applied: Boolean);
begin
DeltaDS.FieldByName('ID').NewValue := GetId('xxx.Id');
end;
3. get 过程如下
function TDictionaryDM.GetId(Name: string): Integer;
begin
这里用的是存贮过程, 也可以用一个 Query实现
getid.Parameters.ParamValues['@NAME'] := Name;
getid.ExecProc;
result := getid.Parameters.ParamValues['@ID'];
if result = -1 then
raise Exception.Create(SKeyNameNotExist);
end;
4. 存贮过程如下
CREATE PROCEDURE getid @ID INT OUTPUT, @NAME VARCHAR(20) AS
BEGIN
UPDATE KEYVALUES SET CURRENTVALUE = CURRENTVALUE + 1 WHERE NAME = @NAME
SELECT @ID = CURRENTVALUE FROM KEYVALUES WHERE NAME = @NAME
IF @ID IS NULL SET @ID = -1
END
4.表结构如下
CREATE TABLE [KeyValues] (
[Name] [varchar] (20),
[CurrentValue] [int]
) ON [PRIMARY]
Top
22 楼comanche(太可怕)回复于 2006-11-03 11:03:21 得分 0
为什么不用自增, 你看了这么多相关后估计也知了,就是说用了自增就只能以 refresh cds 的方法取得正确的数据 id
主从表嘛在服务端绑定问题就有点麻烦了,
1. 主表 id 修改, 这个问严重提高复杂度, 一般让主表 id 新增后不能改, 实际应用也比较多是如此
2. 在 1 的前提下(并不绝对), 主表 id 确定, 从表是 id 新增的
在 DSP 的 UpdateData 事件中写到
var
ChildCDS: TClientDataSet;
begin
// 代码非我正式在用的, 主要为说明问题
ChildCDS := TClientDataSet.Create(nil);
try
while not DataSet.Eof do
begin
if DataSet.UpdateState = dsInsert then
begin
DataSet.Next; 是新增的由 3. 去处理
continue;
end;
ChildCDS.DataSetField := DataSet.FieldByName('DataSetField比方') as TDataSetField;
ChildCDs.First;
while not ChildCDS.Eof do
begin
if ChildCDS.UpdateStatus = usInsert then
ChildCDS.FieldByName('ref_id(比方)').NewValue := DataSet.FieldByName('id').OldValue; // 因为主表 id 不可改
// 要用 NewValue/OldValue, 不能用 Value, 这个DataSet 是 DeltaDS 不存在当前值
// 还有另一些可能性, 不好列举, 实际情况而定, 主表 id 可改就得在下面多写点
ChildCDS.Next;
end;
DataSet.Next;
end;
finally
ChildCDS.Free;
end;
end;
Top
23 楼comanche(太可怕)回复于 2006-11-03 11:14:54 得分 0
3. 在 2 的前提下, 主表 id 新增, 从表 id 也是新增, 前提这些 id 都是生成的
在 dsp 的 beforeupdaterecord 事件中写到
var
NewInsertedId: Integer;
XXXDSPBeforeUpdateRecord(Sender: TObject; SourceDS: TDataSet; DeltaDS: TCustomClientDataSet;
begin
if SourceDS = 主表Query then
begin
if UpdateKind = ukInsert then
begin
NewInsertedId := GetId('xxx.Id');
DeltaDS.FieldByName('ID').NewValue := NewInsertedId;
end
else NewInsertedId := -1;
end
else if (SourceDS = 从表Query) and (NewInsertedId <> -1) then
DeltaDS.FieldByName('Ref_ID').NewValue := NewInsertedId;
end;
end;
这个是个函数入口得有点头晕,
Top
24 楼madyak(无天)回复于 2006-11-03 11:54:35 得分 0
主要是讨论自增ID带来的负作用。处理主从表极为不方便。
Cassava(车超) 说主从表同时增加数据时很简单,严重不同意。
客户端不能每增加一条数据就取一次ID,这和两层没什么区别,如果实现公文包离线工作,这样设计就是找死。
UpdateRecord事件是在一个事务内部反复循环执行,在这里不能为了取ID,出现CLOSE,OPEN,以及执行SQL等语句。除非为这单独建立一个独立的数据连接,但这严重破坏了事物的作用,也大大的降低了性能,弄不好就执行不过去。总之这里不能随意操作数据库。
如果提交前主从表的关联键就已确定,以上这些问题就全部不存在了。
用GUID代替自增ID在开发上要容易的多Top
25 楼fox1999(红狐)回复于 2006-11-03 16:21:57 得分 0
我在第二楼就回答了.
用 GUIDTop
26 楼Cassava(车超)回复于 2006-11-03 17:57:52 得分 0
我觉得我已经写的很明白了,如果还是看不明白,我也没办法,毕竟思路不同Top
27 楼madyak(无天)回复于 2006-11-03 19:36:01 得分 0
Cassava(车超)你那样只是取得ID而已,麻烦的地方是什么时候取,取出来了,如何去用。Top
28 楼zhxfzhxf1(zhxfzhxf1)回复于 2006-11-03 21:16:12 得分 0
xuexiTop
29 楼vfork(學習htm、css、js、java,然後到ajax。)回复于 2006-11-03 23:32:03 得分 0
从头看到尾,终于完了,看累了,我就来总结一下吧!
1.三层中别用AutoID, 这是硬道理.
2.考虑效率问题,不赞同用GUID号做位key,毕竟字符串的比较要花时间的.
3.保证唯一key,可以另建立一张表tbl_mainkey(key_name varchar(10), num int)
每次从num里拿号,然后把num+1,就不会重复了.Top
30 楼3150379(3150379)回复于 2006-11-05 22:23:27 得分 0
Cassava(车超) 的方法是正解,其他方法都是绕圈子或回避问题的主要矛盾。
GUID也是可行的,但太长,没有办法的情况下可以考虑。Top
31 楼3150379(3150379)回复于 2006-11-05 22:29:28 得分 0
主要是讨论自增ID带来的负作用。处理主从表极为不方便。
Cassava(车超) 说主从表同时增加数据时很简单,严重不同意。
客户端不能每增加一条数据就取一次ID,这和两层没什么区别,如果实现公文包离线工作,这样设计就是找死。
==========================================
这段话有问题,添加数据主要由中间层来处理,这也符合多层开发的数据逻辑和企业逻辑,而不是客户端直接让数据库执行它的SQL语句。Top
32 楼madyak(无天)回复于 2006-11-06 08:40:13 得分 0
3150379(3150379) 不知道你看懂了没有?
难点不是如何在数据里取ID,那个存储过程意义不算大。主要是在什么用这个过程,及绑定的方法。如果你有代码请放上来。Top
33 楼madyak(无天)回复于 2006-11-06 08:41:02 得分 0
3150379(3150379) 不知道你看懂了没有?
难点不是如何在数据库里取ID,那个存储过程意义不算大。主要是在什么哪里调用这个存储过程,以及主从表绑定的方法。如果你有代码请放上来。
Top
34 楼Cassava(车超)回复于 2006-11-06 16:03:05 得分 0
madyak(无天)
我觉得我的方法绝对简单,其实我觉得我已经写出了关键,也正确地回答了楼主的问题,
就算延伸到主从表,看了我的代码我想一般的程序员都应该知道怎么做了,madyak(无天)你毕竟是两个星星的的人物,难道就真的不会吗?或还是象前面一样装看不懂呢?如果是装不懂的,我再说破嘴也没用
代码我觉得没什么好贴的了,因为基本上不需要什么代码就基本上能实现了,相信madyak(无天)你是会了的,我也没什么好说的了Top
35 楼madyak(无天)回复于 2006-11-06 16:28:47 得分 0
Cassava(车超) 不要这样说好吗?来得实际的,弄点主从表关联的代码。如果不需要代码,把关键属性设置说说也行呀,不能说空话吧。Top
36 楼skypeople(飞飞)回复于 2006-11-06 16:39:49 得分 0
"加重字段设置默认值(包含自增字段)=找死 (3层用中使用ClientDataset时)"
有些字段不设默认值才是找死;
"用GUID代替自增ID在开发上要容易的多"
GUID会产生效率问题,而且数据库主健关联一旦复杂.这种方式显示非常恶劣;特别某些
要做ORM开发的,会被那个长长的唯一码搞死;
以下回答应该是比较佳的解法;
"
从头看到尾,终于完了,看累了,我就来总结一下吧!
1.三层中别用AutoID, 这是硬道理.
2.考虑效率问题,不赞同用GUID号做位key,毕竟字符串的比较要花时间的.
3.保证唯一key,可以另建立一张表tbl_mainkey(key_name varchar(10), num int)
每次从num里拿号,然后把num+1,就不会重复了.
"
只是要补充一点每访问一次数据库可以取N个ID回来;
Top
37 楼madyak(无天)回复于 2006-11-06 16:46:10 得分 0
我觉得GUID用不用并不是关键,关键是在客户端,起关联作用的键,在提交前就要确定下来,至于如何确定根据具体情况决定。提交前用不确定的值做关联确实增加了很大的负担。Top
38 楼Cassava(车超)回复于 2006-11-07 16:02:47 得分 0
既然返回了主表的关联ID,那么就和操作单表差不多了,还有什么好说的呢
Top
39 楼madyak(无天)回复于 2006-11-07 16:51:46 得分 0
Cassava(车超) 我很纳闷,你做过三层没有?你返回到哪去,客户端还是服务端?Top
40 楼Cassava(车超)回复于 2006-11-07 17:54:33 得分 0
Cassava(车超) 我很纳闷,你做过三层没有?你返回到哪去,客户端还是服务端?
你是不是没做过三层呀?
觉得你没有客户端和服务端的概念
----------------------------------------
虽然水平没你高了,但请不要怀疑我没有做过三层啊
返回客户端
Top
41 楼madyak(无天)回复于 2006-11-07 17:57:58 得分 0
呵呵,那你是不是在客户端每增加一条数据,就要提交一次数据呢?
如果你真这样做三层,我无话可说。Top
42 楼Cassava(车超)回复于 2006-11-07 18:20:16 得分 0
回传ID到客户端的当然是先添加主表记录,从表可以在客户端添加完了,再更新到数据库。
如果想主从表都在客户端添加完了,再一次性提交到服务器更新到数据库也是可以实现的
先输完主从表数据,然后写一个主从表更新的接口方法把数据传到服务器,然后服务器先调用存储过程先添加主表数据且
返回ID到服务端,然后再根据返回的主表关联ID再添加从表的数据进数据库Top
43 楼Cassava(车超)回复于 2006-11-07 18:22:57 得分 0
如果主从表都是单一的数据,那么只需要调用存储就能实现了,
如:
CREATE PROCEDURE aaa
as
declare @AutoID int
inser into a(a)values('a')
set @AutoID=SCOPE_IDENTITY()
inser into b(AutoID,a)values(@AutoID,'b')
Top
44 楼madyak(无天)回复于 2006-11-07 19:29:40 得分 0
你上面不是说,不需什么代码吗?早这样说不就结了,这就是你说的不需代码般的简捷吗?Top
45 楼Cassava(车超)回复于 2006-11-07 21:46:22 得分 0
如果是返回id到客户端,是不需要什么代码就可以实现了的啊
如果是同时提交是需要多写些代码,但这些代码也不是很复杂啊
主从表都是单一记录数据的,就更简单了啊Top
46 楼quicksand201(流沙)回复于 2006-11-08 00:15:10 得分 0
就事论事,如果每次做主从关联都要先从数据库取唯一标识,这样网络的流量会很大
最好这个唯一标识由中间层管理,不过这样做工作量会大很多Top
47 楼3150379(3150379)回复于 2006-11-09 08:30:06 得分 0
晕,还吵起来了啊?madyak(无天),别看你有两个星星,谦虚点好不,程序设计不是一成不变的,相同的功能实现方法很多,而这些实现方法的好坏标准也不一样,那要视功能细节要求而定,别总陷到自己的模式里。
楼主的提问非常简捷“在三层中,自增字段(id),在新增完数据后,需要返回id,用delphi的数据感知控件,能实现吗?”,有些文学功底的人都能够看出来他的困惑是不知道如何取得返回ID,你在这里吵什么,你说的那些如果说有道理的话,也仅限在你的思维模式下罢了。
你以为说一句“主从表”就表述很清楚了吗?给你举个例子吧,你的目的是从A城市到B城市,你跟我说说是坐“飞机、火车、汽车”这三种方式最先到达?AB距离、天气、路况、机场和车站远近等等你都不知道,你还吵着说坐XXX肯定快,简直笑话。Top
48 楼madyak(无天)回复于 2006-11-09 09:05:32 得分 0
3150379(3150379)谦虚二次用得极为不当,如果在这里大家都谦虚的话,互相推让着答问题,或者知道也装着不知道,我看论坛就应该关闭了。
凡事没有绝对的,只是说一个比较实用的规则而已。看楼主问得问题,应该是对三层开发有很多细节上的东西不太了解。说这些只是提醒他注意,用自增ID后面可能会有很多的麻烦
3150379,不知道你是谁的马甲,信誉度怎么这么低?
回答问题时,不见你的影子,有人回答了,你来说风凉话。是不是建议大家都象你学习呢?
Top
49 楼comanche(太可怕)回复于 2006-11-09 09:19:01 得分 0
不要火药味那么大嘛
认真看完了贴子内容后, 发现都是可以达成目标的, 不过偶本人是不支持Cassava(车超) 的作法, 过于浪费网络, 如果客户机在广域网上是非常慢的, 公文包模式现在基本上认为是必须的
楼主不见了呵, 看看楼主怎么说Top
50 楼madyak(无天)回复于 2006-11-09 11:00:56 得分 0
很久没这样争论过了。
只是觉得在三层用自增ID麻烦,尤其是牵涉到主从表。如果再是个新手,弄不好做出来的东西是三层外表,两层的骨头。如果想做好,就必需有专门处理ID主从绑定的代码,这样一弄明显增加了工作量。对老手还不要紧,但对新手来说,绑定这部分很难,至少我不愿意这么干,除非在特殊环境下,不得已而为之。
处理这些主从表同时增加,个为觉得核心代码和主要逻辑是如何绑定主从,且比较麻烦,尤其是一主对多从,或者主-半主-从串联起等。有人反对没什么,只是他们坚持自己的观点,但不拿出解决这些问题的办法。简单点就是有论点,没论据,吵了半天才说出来了一些。为了坚持用自增ID的可用性和不复杂性,却一字不提主从绑定的部分,这对新手来说是误导。
问题焦点不是能不能解决,而是解决起来很麻烦,如果提前主从关联外键就是已知了,这样明显减小了不小的工作量。Top
51 楼3150379(3150379)回复于 2006-11-09 11:01:19 得分 0
madyak(无天) :
1、“3150379,不知道你是谁的马甲”这是我唯一的号,请不要以小人之心度君子之腹。
2、“信誉度怎么这么低?”信誉度低怎么了,你挂着两个星觉得好看是你的事,信誉度低的技术上就不如你了吗,可笑。
3、“回答问题时,不见你的影子”一定要整天在这里回答问题的人才有权利在这里讨论吗?笑话。
4、“有人回答了,你来说风凉话。”争开你的眼睛仔细看看,哪一句是风凉话,你回答问题,我也回答问题,不同意你的观点就叫风凉话吗?
5、别总是说话盛气凌人的,你自己回头看看自己说的话,好象就你设计过三层结构,就你有经验,即使是这样,也应该谦虚一些吧,本人不才,N层结构也设计了一些,楼主这个问题我也曾经遇到过,但Cassava(车超)说的方法确实可行,我也没有说其他办法不行,只是说他的方法算是正解,你别总是网络流量网络流量的,就你知道广域网程序设计要考虑网络流量?别人都不知道?好象Cassava(车超)的方法就注定了要增加网络流量一样,可笑,只能说明你的设计思路太单一罢了。Top
52 楼madyak(无天)回复于 2006-11-09 11:28:50 得分 0
请你不要误解,俺可没说你技术水平低,论坛里有很多高手是一个小角。
说我盛气凌人,我不并觉得。只是我说自增ID的负面作用的几个问题。只是有人闭着眼说,自增ID好,有多么多么好,而不正面回答问题。如果一个系统以自增ID结构为主,只那个存储过程,是远远不够的,必需有一个系统的针对那些问题的解决方案。
如果你坚持说这样很简单,没有增加工量作,我没话可说。
也许你是高手吧。希望你能在论坛上多解决些问题,不建议所有象你一样的高手在这里潜水或者太谦虚了。也许你很少在网上发表些见解,这个贴中算是难得一见了,从你的一个角上就能看出来。希望在这个主题里没有影响到你。
很久不用DELPHI了,但本人对DELPHI还是很有感情的,偶尔也来一下看看,增加些人气。
Top
53 楼cobi(我是小新)回复于 2006-12-07 12:05:26 得分 0
似乎这里好久没有这么热闹的帖子啦!凑个热闹
我是今年年初写三层服务器程序的时候发现不能用自增字段的(sorry,好久没动手了,有些东西都忘得差不多了)。当时我的做法就是一般的处理:cds-datasetprovider-adoquery,设置了datasetprovider的属性popropogateChanges为true,目的是服务器能够在完成更新后可以把id回传,结果运行出错,提示autoinc字段不能这样处理。上BDN查找了一下,也就是发现了http://bdn.borland.com/article/20847这个帖子,好像还有一个吧,按照里面的介绍修改了provider.pas的代码,也不通过。估计这个是delphi的bug吧~所以在设计上也就没有使用autoinc字段了~
至于大家这里争论的,我觉得有点抓不住关键吧~Cassava(车超)的回复是如何去获取一个可增的Id,但显然用存储过程获取的Id不是这个概念上的自增加id吧!自增加字段应该是新增记录保存后由数据库自行分配的一个值,这个值不用我们去关心。而我们用存储过程获得的id,则是我们可以使用规则定义并产生的一个字段值,所以我认为这里是两个不同的概念。
按照楼主的提法,他应该是希望使用一个id由数据库产生并回传。根据我自己的实验记录,不应该直接使用autoinc字段,自己定义一个字段(int或varchar的都可以),通过后台存储过程计算这个字段的值并在中间层进行赋值处理就可以了。ddqqyy(ddqqyy)的回复里面给出了完整的思路,BDN的例子也是这样处理的。
不过,ddqqyy(ddqqyy)的回复里最后用到了clientdataset.refresh,其实没有必要这样做。只要datasetprovider的属性popropogateChanges为true,后台所作的修改就会自动提交到客户端,注意,被提交数据中在中间层被修改了的才会回传,这样子网络的负荷会明显少很多。而refresh则是对clientdataset中的所有数据进行一次再查询,这个负荷会很大
这是我对三层里面使用自增字段的一些看法,请各位指教指教Top
54 楼dovelee(黑土)回复于 2006-12-07 17:56:21 得分 0
好帖!很过瘾啊!Top
55 楼Northwindrocker(北风)回复于 2006-12-07 19:24:32 得分 0
看了半天学习了很多,不过总结下来还是oracle简单,一个sequence解决这个问题,需要用自增用sequence产生,sequence的当前数可以查到。Top
56 楼Northwindrocker(北风)回复于 2006-12-07 19:29:51 得分 0
但是我认为
********************************************
回复人:Cassava(车超) ( 五级(中级)) 信誉:100 2006-11-7 18:22:57 得分:0
?
如果主从表都是单一的数据,那么只需要调用存储就能实现了,
如:
CREATE PROCEDURE aaa
as
declare @AutoID int
inser into a(a)values('a')
set @AutoID=SCOPE_IDENTITY()
inser into b(AutoID,a)values(@AutoID,'b')
************************************************
这段代码是可取的,实际上是把数据库自动产生的ID让数据库自己去处理。并不需要回传到client端阿,这样的存储过程我也是写过的。不过我没做过三层,不敢说这个就一定适合三层。
Top
57 楼madyak(无天)回复于 2006-12-07 19:46:38 得分 0
呵呵,很久不用DELPHI了,生怕再忘光了。当年这可是吃饭的家伙。Top
58 楼ChangWeiTu(常伟图)回复于 2006-12-08 15:11:04 得分 0
强烈鄙视问题解决后不结贴的人!
强烈鄙视技术问题解决后把贴子转移到非技术区的人!
鄙视你们!
http://community.csdn.net/Expert/topic/5216/5216675.xml?temp=.9262659Top




