第二次插入时无效的事务对象

时间:2015-01-05 15:59:54

标签: database delphi

我有3个插入客户端的功能。我正在使用mysql的事务。我正在看这个页面中的其他帖子有相同的例外,但我的代码是正确的。问题是我第二次尝试插入客户端,我的意思是:我在Delphi中打开应用程序,正确插入一个客户端。但是其他客户端给我一个例外:远程错误:无效的事务对象。

以下是代码:

function TServerMethods1.insertarcliente( idlocalidad, DNI, cuit, cuil, cupodias: integer; descuento, cupocheques, cupopesos, cupochequestro: Double;
  domicilio, nombreyape, direccion, email: string ): boolean;
var
  uubicacion, upersona, ucliente: integer;
  tr: tdbxTransaction;
  exito: boolean;
begin
  SUCURSAL.Open;
  tr := SUCURSAL.BeginTransaction( );
  try
    begin
      with qipersona do
        begin
          Close;
          ParamByName( 'DNI' ).AsInteger := DNI;
          ParamByName( 'nombreyape' ).AsString := nombreyape;
          ParamByName( 'direccion' ).AsString := direccion;
          ParamByName( 'email' ).AsString := email;
          ExecSQL( );
          Free;
        end
    end
  except
    SUCURSAL.RollbackFreeAndNil( tr );
  end;
  try
    begin
      with qicliente do
        begin
          Close;
          ParamByName( 'idpersona' ).AsInteger := qucli.ExecSQL( );
          ParamByName( 'cuit' ).AsInteger := cuit;
          ParamByName( 'cuil' ).AsInteger := cuil;
          ParamByName( 'deuda' ).AsFloat := 0.00;
          ParamByName( 'cupodias' ).AsInteger := cupodias;
          ParamByName( 'cupocheques' ).AsFloat := cupocheques;
          ParamByName( 'cupopesos' ).AsFloat := cupopesos;
          ParamByName( 'cupochequestro' ).AsFloat := cupochequestro;
          ParamByName( 'descuento' ).AsFloat := descuento;
          ExecSQL( );
          Free;
          SUCURSAL.CommitFreeAndNil( tr );

          exito := True;
        end
    end
  except
    SUCURSAL.RollbackFreeAndNil( tr );
  end;
  Result := exito;
end;

function TServerMethods1.insertartelefonoscliente( numero, idtipotel: integer; descripciontel: string ): boolean;
var
  tr: tdbxTransaction;
  exito: boolean;
begin
  SUCURSAL.Open;
  if ( SUCURSAL.InTransaction = False )
  then
    tr := SUCURSAL.BeginTransaction( )
  else
    begin
      try
        begin
          with qtelefono do
            begin
              Close;
              ParamByName( 'numero' ).AsInteger := numero;
              ParamByName( 'idtipotel' ).AsInteger := idtipotel;
              ParamByName( 'descripcion' ).AsString := descripciontel;
              ExecSQL( );
              Free;
            end;
        end;
        // si no se pudo
      except
        begin
          SUCURSAL.RollbackFreeAndNil( tr );
          exito := False;
        end;
        try
          with telcli do
            begin
              Close;
              ParamByName( 'idc' ).AsInteger := qucliente.ExecSQL( );
              ParamByName( 'idt' ).AsInteger := qut.ExecSQL( );
              ExecSQL( );
              Free;
            end;
        except
          SUCURSAL.RollbackFreeAndNil( tr );
          exito := False;
        end;
        SUCURSAL.CommitFreeAndNil( tr );
      end;
      Result := exito;
    end;
end;

function TServerMethods1.insertarubicacionescliente( idlocalidad: integer; domicilio, descripcion: string ): boolean;
var
  tr: tdbxTransaction;
  exito: boolean;
begin
  SUCURSAL.Open;
  if ( SUCURSAL.InTransaction = False )
  then
    tr := SUCURSAL.BeginTransaction( )
  else
    begin
      try
        with qiubicacion do
          begin
            Close;
            ParamByName( 'idlocalidad' ).AsInteger := idlocalidad;
            ParamByName( 'domicilio' ).AsString := domicilio;
            ParamByName( 'descripcion' ).AsString := descripcion;
            ExecSQL( );
            Free;
          end;
        // si no se pudo
      except
        SUCURSAL.RollbackFreeAndNil( tr );
        exito := False;
      end;
      try
        with quper do
          begin
            Close;
            ParamByName( 'idp' ).AsInteger := qup.ExecSQL( );
            ParamByName( 'idu' ).AsInteger := quu.ExecSQL( );
            // ParamByName('descripcion').AsString:=descripcion;
            ExecSQL( );
            Free;
          end;
        SUCURSAL.CommitFreeAndNil( tr );
      except
        SUCURSAL.RollbackFreeAndNil( tr );
        exito := False;
      end;
      Result := exito;
    end;
end;

1 个答案:

答案 0 :(得分:0)

你声称"我的代码是对的&#34 ;;但实际上并非如此。例如:在第一种方法中,您执行以下操作:

  • 开始交易。
  • 运行qipersona查询
    • [A] 如果运行查询时出错,则会捕获异常并回滚事务。
  • 然后继续运行下一个查询,就好像没有出错一样。
    • [B1] 如果成功,则提交交易。
    • [B2] 如果失败,则回滚事务。

如果 [A] 发生,那么 [B1] [B2] 都会保证失败,因为您正在尝试提交或回滚已经回滚的事务

[B2] 失败时,您将在块中获得异常,并且它会转义到外层处理程序。

要正确解决您的问题,您需要停止隐藏/吞咽异常,以便您可以查看问题的实际根本原因。

使用以下结构:

StartTransaction
try
  RunQuery1
  RunQuery2
  ...
  CommitTransaction
except
  RollbackTransaction
  raise; //This is VERY IMPORTANT ... 
         //Don't swallow exceptions and you'll have
         //a much easier time finding your bugs.
end;