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