| 关于 adoDataset的SavetoFile和LoadFromFile引起的问题 |
| [ 来源:ITWENKU 时间:2006-9-11 14:55:26 | 浏览:261人次
] |
| |
|
现在如下过程,用于单击按钮时保存用户数据:
------------------------------------------------ ------------------------------------------------ procedure Tfmbs_Major.btnSaveClick(Sender: TObject); Var TempFile:String; RecNO:Integer; IsInsert:Bool; SQL_BeforePost:WideString; begin //inherited; 只可放在最后,否则,数据提交有误时,系统会一样的按btnSetbtns.click
TempFile:= global_AdoSaveDir + '\Major.Dat' ; RecNO := adoMain.RecNo ; IsInsert:= adoMain.State =dsInsert;
IsAborted:=False; IsShowedErr:=False; IsPostOK:=True;
adoMain.SaveToFile( TempFile ); //不会调用post
if IsPostOK=False then begin exit; //提交数据时有错, IsPostOK放在 Dataset.BeforePost中,用于检测数据是否合法 end; try if not adoMain.Connection.InTransaction then begin adoMain.Connection.BeginTrans; end;
if adoMain.LockType =ltOptimistic then adoMain.Post else if adoMain.LockType =ltBatchOptimistic then adoMain.UpdateBatch(arAll);
if adoMain.Connection.InTransaction then adoMain.Connection.CommitTrans;
myDeleteFile( TempFile); except on E:Exception do begin if adoMain.Connection.InTransaction then begin adoMain.Connection.RollbackTrans; end;
adoMain.LoadFromFile( TempFile);
if IsInsert then adoMain.Last else try adoMain.RecNo:= RecNO; except ; end;
if IsAborted=False then myShowErr('保存数据时失败!原因:' + #13 + E.Message ); exit; end; end; //end try
myShowInfo('数据已成功保存!','保存'); end; ----------------------------------------------------- ----------------------------------------------------
问题:
数据库是Access(其实,应该与数据库无关,估计SQL Server也是一样)。 如果用户提交数据有重复的键值,即系统显示类似:
由于将在索引、主关键字、或关系中创建重复的值,请求对表的改变没有成功。...... 的信息时,再次执行下面的语句时:
adoMain.close; adoMain.commandText:='Select * from bs_Major'; adoMain.open;
时,系统报错。提示:
“文件 Select * from bs_major 无法被找到。”
大家看清了,哪怕我作一个按钮,强制执行上述三行语句,都是出此问题,但是,如果用户提交的数据是其它错误而非主键错误,程序又很正常。特别奇怪的是,系统提示“文件 Select * from bs_major 无法被找到。”后,我用Try ...end 跟踪调试发现,adoMain.CommandText 的值是正常的,没有错误。
大家可能会问为什么一定要用 SaveToFile和LoadFromFile呢? 原因是:如果不用此方法,那么用户提交的数据发生主键重复时,即使用户把冲突的主键数据改正过来了,保存后,系统总是只保存最后那条记录。
含泪求各位大虾伸出援助之手: 1、解释上述错误发生之原因; 2、给小弟一个解决方案!
小弟三生都会记住你的好。
补充: adoMain是 adoDataset
adoMain的beforepost是有代码: 如下: ---------------------------- procedure Tfmbs_Major.adoMainBeforePost(DataSet: TDataSet); Var RecNO:integer; myFieldName:String; myField:TField; begin //inherited; RecNO:=Dataset.RecNo;
IsShowedErr:=False; IsAborted:=False; IsPostOK:=False; if (adoMain.FieldByName('MajorNO').AsString='') or (adoMain.FieldByName('MajorName').AsString='') or (adoMain.FieldByName('StudyYears').AsInteger=0) then begin myShowErr('专业代码、名称不可为空或学制不可为0!'); IsShowedErr:=True; IsAborted:=True; Abort; Exit; end;
with adoMyTemp do begin Close; CommandText:='Select Count(DepartNO) as SumRec from bs_Major Where MajorNO=:MajorNO'; Parameters.ParamByName('MajorNO').Value :=adoMain.FieldByName('MajorNO').AsString; Open;
if ( (Dataset.State =dsInsert) and (FieldByName('SumRec').AsInteger>=1 ) or (Dataset.State =dsEdit) and (FieldByName('SumRec').AsInteger>=2 ) ) then //处于编辑状态时不能这样查询 begin if adoMain.Connection.InTransaction then adoMain.Connection.RollbackTrans; myShowErr('当前专业代码已经存在!' + #13 + '重复的代码:' + Dataset.FieldByName('MajorNO').AsString); //Dataset.RecNo:= RecNO; IsShowedErr:=True; IsAborted:=True; Abort; Exit; end; Close; end; end;
大家再帮忙一下呀
从你现在的代码看不出使用事务的必要性,为什么要用事务,事务一般用于同时修改多个表,同时要保证数据的完整性才使用的,你这里我觉得是多此一举。 另外你要做的事情也没有必要保存到硬盘文件,纯粹是浪费一次还要访问硬盘的时间,你的表有几个显示的字段,为了界面友好,了不起,Post前多用几个内存变量保存下当前界面上所有的数据,post出错,用这些变量恢复界面。 这样绝对可行的,要知道你不是同时保存多条记录,移动表光标的方法比如Next是自动调用Post的,所以每次Post都是一条记录,所以一组简单变量就能满足你的要求。
|
|
 |
推荐文章 |
|