现在如下过程,用于单击按钮时保存用户数据:------------------------------------------------
------------------------------------------------
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、给小弟一个解决方案!  小弟三生都会记住你的好。

解决方案 »

  1.   

    看看beforeopen和afteropen事件有没有代码?(甚至beforepost等)不用savetofile等也可以,locktype类型中的用第一个,缓冲,ADODataSet1.post时保存到缓存,
    ADODataSet1.UpdateBatch才是提交到数据库
      

  2.   

    补充:
      adoMain是 adoDataset
      

  3.   

    dabaicai(不再做菜鸟):
      检测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;
      

  4.   

    代码没什么问题,看来不看全部代码不容易找了....建议还是用缓冲方法吧,加一个dataset,里面把关键字查出来,用户增加数据的时候,用locat来找看是否已经存在来判断也可以注:代码Abort;之后不需要Exit了