Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database 第二次插入时事务对象无效_Database_Delphi - Fatal编程技术网

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

Database 第二次插入时事务对象无效,database,delphi,Database,Delphi,我有3个函数来插入客户机。我正在使用mysql的事务。我在这页上看了其他帖子,它们也有同样的例外,但我的代码是正确的。问题是我第二次尝试插入客户机时,我的意思是:我在Delphi中打开应用程序,正确地插入了一个客户机。但其他客户端给了我一个异常:远程错误:无效的事务对象 代码如下: function TServerMethods1.insertarcliente( idlocalidad, DNI, cuit, cuil, cupodias: integer; descuento, cupoch

我有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;


你声称“我的代码是正确的”;但事实并非如此。例如:在第一种方法中,您可以执行以下操作:

  • 开始一项交易
  • 运行
    qipersona
    查询
    • [A]如果运行查询时出错,您将捕获异常并回滚事务
  • 然后继续运行下一个查询,就好像什么都没有出错一样。
    • [B1]如果成功,则提交事务
    • [B2]如果失败,则回滚事务
如果发生[A],则[B1][B2]都保证失败,因为您试图提交或回滚已回滚的事务

[B2]失败时,您将在except块中得到一个异常,它将转义到外部级别处理程序

为了正确地解决问题,您需要停止隐藏/吞咽异常,以便能够看到问题的实际根本原因

使用以下结构:

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;

我不确定您在这里要问什么,但请注意,您可以释放每个查询对象,例如
qipersona
。我看不到任何实例化…提交和回滚的
版本的
FreeAndNil
做什么,以及
SUCURSAL
是什么类型?你正在吞咽异常,然后继续进行,就好像什么都没有出错一样。这是灾难的秘诀。你还没有告诉我们到底是哪一行代码产生了错误。我不知道哪一行是代码,因为客户端应用程序正在运行@kobik:我也没有看到任何实例化,但我认为对象sucursal(是clientdatamodule中的tsqlconnection到datasnap服务器)可能会被实例化。@用户,我的观点是,您在第一次调用该方法后销毁了该对象(通过使用qipersona do…Free的
)。因此,在您第二次调用该方法时,对象已经被销毁,并且由于您的
except
没有抛出任何异常,因此您可能会得到这种行为。虽然您对所有这些都是正确的,但您没有抓住要点。在第一次成功执行
qipersona
后,此实例被释放,并导致第二次调用的异常->无效reference@SirRufo同意。当事务处理和异常吞咽被修复后,OP将看到由于销毁不应该在那里销毁的对象而导致的访问冲突错误。但是,如果只修复了根本原因,那么在第一次查询由于密钥冲突或不匹配的Db模式而失败之前,一切都会正常进行。从教学的角度来看,我认为首先应用事务和异常修复是很重要的。如果Excel 2查询:提交和回滚是每个事务的一个,因为我想这是每个事务的一个查询。我想:如果你不能插入到角色中,你将无法插入到客户中,那么你需要回滚。@user3780282你应该深入了解异常是如何发生的work@user3780282事务的全部要点是确保对于一组查询:要么全部成功,或者,如果存在任何错误,则不会更改任何内容。因此,无论组中有多少查询,您都需要一个事务。1开始,1提交,如果一切都成功,1回滚,如果出现任何问题。
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;
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;