同意liang_z(千山一刀之忍者神龟) 的,不过我觉得没那么复杂,刚好我最近也解决了此类的并发数据采集问题我的解决方法是:在SQL SERVER数据库中写一个申请锁的存储过程,程序运行时,每次都要先申请锁,申请成功则采集。存储过程很简单(如下) CREATE PROC P_SetLock @DeptCode VARCHAR(5), @RetVal INT OUTPUT AS BEGIN TRAN SELECT @RetVal = Coll_Start_Sign FROM T_DepaInfo WITH(UPDLOCK) WHERE New_Depart_Code=@DeptCode IF @@ERROR <> 0 BEGIN SET @RetVal = -1 END IF @RetVal <> 2 AND @RetVal <> 1 BEGIN SET @RetVal = 0 END ELSE BEGIN SET @RetVal = -1 END IF @RetVal = 0 BEGIN UPDATE T_DepaInfo SET Coll_Start_Sign = 2 WHERE New_Depart_Code=@DeptCode END IF @@ERROR <> 0 BEGIN SET @RetVal = -1 END COMMIT TRAN
对于第一种方法的补充:
如果万一产生冲突的话,还可以解决:
捕获数据库的异常,当异常是主键冲突的话,表示取出的当前号已被占用,你就再重新去取号,并且可以设置重试次数,比如如果重取5次还是冲突的话就让用户稍等会再存盘!有点象ftp登录服务器一样,但不能无限制去重试,否则将加重服务器的负担!如果觉得我的意见可以的话,请适当给我加点分,我就快升级了!呵呵!
则你可以用一个全局临时表来解决问题,
在入库单新增时调用一个存储过程,
在过程中取得最大的编号+1,
看这个编号有没有全局临时表如:##HL000010,
如果有则+1后再判断,
如果没有则用本编号建一个全局临时表如##HL000013,
临时表的数据列刚好作为明细表的数据缓冲,
要保存时,还可以用一个存储过程在事务中来处理主细表的同时更新问题。用这个办法的好处是可以事先得到单据编号,并不会冲突,还可以用事务来
保证数据的一致性。
CREATE PROC P_SetLock
@DeptCode VARCHAR(5),
@RetVal INT OUTPUT
AS
BEGIN TRAN
SELECT @RetVal = Coll_Start_Sign FROM T_DepaInfo WITH(UPDLOCK) WHERE New_Depart_Code=@DeptCode IF @@ERROR <> 0
BEGIN
SET @RetVal = -1
END IF @RetVal <> 2 AND @RetVal <> 1
BEGIN
SET @RetVal = 0
END
ELSE
BEGIN
SET @RetVal = -1
END IF @RetVal = 0
BEGIN
UPDATE T_DepaInfo SET Coll_Start_Sign = 2 WHERE New_Depart_Code=@DeptCode
END
IF @@ERROR <> 0
BEGIN
SET @RetVal = -1
END COMMIT TRAN
一切ok!