问题是这样的,我做了一个小的仓库管理,在对‘入库表’中进行的一些操作时能够让‘库存表’也及时的改动,即在增加入库记录时,库存中的总数和现有库存也要增加。
procedure TForm1.Button1Click(Sender: TObject);
begin
   adoquery1.Insert;                       //增加按钮
   adoquery1.FieldByName('in_date').AsDateTime:=Today();
end;
procedure TForm1.addDevice(Acode:string;ANumber:integer);
 var is_sql:string;
begin                                     //通过这个函数来对库存表修改
  is_sql:=format('update device set now_number=now_number+%d,total=total+%d where code=%s',[ANumber,ANumber,quotedstr(Acode)]);
  with DataModule2 do
  begin
    adoquery1.Close;
    adoquery1.SQL.Clear;
    adoquery1.SQL.Text:=is_sql;
    adoquery1.ExecSQL;
  end;
end;
这里面还有ADOQuery1BeforePost、ADOQuery1AfterPost、ADOQuery1PostError三段代码里面分别是针对操作的事务处理。
编译没有问题,但是运行时出现了错误。
Debugger Exception Notfication
   X   project Project1.exe raised exception class EDdatabaseError with message 'ADOQuery1:Cannot perform theis operation on a closed dataset'.Process stopped. Use Step or Run to continue.
   错误的行就是在: adoquery1.FieldByName('in_date').AsDateTime:=Today();
   我把它注死掉后错误就在下一行了:end;
我的用的数据库是Access, 但是我用SQL Server数据库也一样。不过SQL的数据库是从ACCESS中导入的。请各位能帮帮忙指点小弟一下,不胜感激!

解决方案 »

  1.   

    adoquery1.Insert; 
    ~~~~~~~~~~~~~~~~~~~~
    之前,adoquery1是否有返回数据,是否打开数据集(open)
      

  2.   

    procedure TForm1.ADOQuery1BeforePost(DataSet: TDataSet);
    begin
        DataModule2.ADOConnection1.BeginTrans; //开始一个事务
        try
          if adoquery1.State in [dsinsert] then    //增加
           addDevice(adoquery1.fieldbyname('code').AsString,adoquery1.fieldbyname('in_number').AsInteger)
          else if adoquery1.State in [dsedit] then   //修改
           begin
            if adoquery1.FieldByName('code').NewValue<>adoquery1.FieldByName //修改的是设备号('code').OldValue then
            begin
             addDevice(adoquery1.fieldbyname('code').OldValue,-adoquery1.fieldbyname('in_number').OldValue);
             addDevice(adoquery1.fieldbyname('code').NewValue,adoquery1.fieldbyname('in_number').NewValue);
            end
            else
            if adoquery1.FieldByName('in_number').NewValue<>adoquery1.FieldByName('in_number').OldValue then   //修改的是数量
            begin
              addDevice(adoquery1.fieldbyname('code').AsString,-adoquery1.fieldbyname('in_number').OldValue);
              addDevice(adoquery1.fieldbyname('code').AsString,adoquery1.fieldbyname('in_number').NewValue);
            end;
          end;
        except
         on E:exception do
         begin
          showmessage(e.Message);
          DataModule2.ADOConnection1.RollbackTrans;  
          abort;
         end
       end;
    end;procedure TForm1.ADOQuery1AfterPost(DataSet: TDataSet);
    begin
       DataModule2.ADOConnection1.CommitTrans;   //提交
    end;procedure TForm1.ADOQuery1PostError(DataSet: TDataSet; E: EDatabaseError;
      var Action: TDataAction);
    begin
        DataModule2.ADOConnection1.RollbackTrans; //错误回滚
    end;
    这基本上是这个程序的全部代码了,还请大家多多指教一下,有什么其它的好办法也希望大家能说一下,越详细越好! 先谢谢各位了!
      

  3.   

    adoquery1.Close;
    你自己不是关闭了数据集吗?
    关键是你不能用一个ADOQUERY又做数据集又执行SQL指令。
      

  4.   

    TO:gxgyj(Jackson...) 
    在Adoquery1的SQL属性中有查询的语句:select * from device_in
    但是Action属性打不开,提示错误:ADOQuery1:Fiedl 'IN_date' not found.
    在device_in数据表中确实存在'IN_date'这个列名,为什么会出现错误提示咧?
    盼赐教!
      

  5.   

    你看段我的事務回滾
    procedure TForm1.suiButton1Click(Sender: TObject);//调用程序
    var
      tempvar:string;
    begin
      tempvar:='aaaaaaaa';
      sqlexec('update pz set bh=:tempvar where bh=:edtbh.Text');
    end;//sqlexec的函数
    procedure sqlexec(sqlcommstring:string); //插入、更新、删除等SQL操作
    begin
    with dataSetAll do
      begin
        ADOQuery1.Close;
        ADOQuery1.SQL.Clear;
        adoconn.Close;
        adoconn.Open;
        adoconn.BeginTrans; //开始事务处理
        try
          ADOQuery1.SQL.Add(sqlcommstring);
          ADOQuery1.ExecSQL;
          adoconn.CommitTrans;//提交事务处理
        except
          adoconn.RollBackTrans;//回滚事务处理
        end;
      end;//DMl1.ADOQuery1.SQL.Add( values ('+EdtNo.Text+','+QuotedStr(EdtName.Text)+','+QuotedStr(EdtSex.Text)+');
              DMl1.ADOQuery1.execSQL;          //Parameters.ParamByName('cy1').Value := strToInt(EdtNo.text);
              //Parameters.ParamByName('cy2').Value := Trim(EdtName.text);
              //Parameters.ParamByName('cy3').Value := Trim(EdtSex.text);
              //ExecSQL;
            //  close;
           //*******Query1****************//
               //SQL.clear;
               //SQL.Add('insert into Tbl1');
               //SQL.Add('values(:v1,:V2,:V3)');
               //ParamByName('V1').asInteger:=strtoint(Trim(EdtNo.Text));
               //ParamByName('V2').asString:=Trim(EdtName.Text);
      

  6.   

    adoquery1没有被打开,open就可以了
      

  7.   

    呵呵,谢谢大家了。的确是数据集没有打开的原因
    procedure TForm1.Button1Click(Sender: TObject);
    begin
       adoquery1.open;   //添加后
       adoquery1.Insert;                       //增加按钮
       adoquery1.FieldByName('in_date').AsDateTime:=Today();
    end;
    但是打开后的数据有错误了(入库数量和数据库中根本不同了),我点添加按钮也一样显示的数据是错误的,到现在为止程序的功能还是不能执行(应该是事务处理方面有问题,我再改改),但是我想请问一下数据错误是怎么来的啊?我在设计时把adoquery1的action改成True时就错了。
      

  8.   

    TO: dinglinger(红辣椒) 
    我是想用adoquery1来操作“入库表”的,并将操作的结果用数据模板上的另一个adoquery来执行事务(DataModule2.ADOConnection1.BeginTrans;),功能的实现就由函数procedure TForm1.addDevice(Acode:string;ANumber:integer);来做,这样是不是不可行啊?
    TO: QWERT520(别来无恙)
    谢谢你提供的例子,但是我的所有操作(增加、删除、修改、保存...)都是要在数据显示控件上完成(DBGrid).有什么好的实现方法没,还烦请你帮忙提供一下。感激不尽!