【发布时间】:2014-10-03 15:12:16
【问题描述】:
我正在使用 MySQL,并且我知道嵌套连接是不允许的 - 为此使用“保存点” - 但我想创建一个更通用的代码,也可以与其他 DBMS 一起使用。
那么,我想知道如何在下面的代码中正确启动、工作和完成事务?
一旦ExampleDAO.Save() 函数可以在其他函数中使用,例如OtherExampleDAO.Save(),我需要在尝试启动新事务之前验证事务是否已启动。
验证if Assigned(dbTransaction) then的行总是返回true,那么如何正确验证dbTransaction是否被实例化了?
function TExampleDAO.Save(const Example: TExample): Boolean;
var
dbxTransaction: TDBXTransaction;
begin
if Assigned(Example) then // prevents invalid object, like ExampleDAO.Save(nil);
begin
try
if (_connection.TransactionsSupported) AND
((not _connection.InTransaction) OR (_connection.MultipleTransactionsSupported)) then
begin
dbxTransaction := _connection.BeginTransaction(TDBXIsolations.ReadCommitted);
end;
try
// example
_sqlQuery.Close;
_sqlQuery.SQL.Clear;
_sqlQuery.SQL.Add('INSERT INTO example(a, b) '
+ 'VALUES(:a, :b)');
_sqlQuery.ParamByName('a').AsAnsiString := Example.A;
_sqlQuery.ParamByName('b').AsDateTime := Example.B;
_sqlQuery.ExecSQL(False);
// example info
_sqlQuery.Close;
_sqlQuery.SQL.Clear;
_sqlQuery.SQL.Add('INSERT INTO example_info(c, d) '
+ 'VALUES(:c, :d)');
_sqlQuery.ParamByName('c').AsInteger := Example.Info.C;
_sqlQuery.ParamByName('d').AsFloat := Example.Info.D;
_sqlQuery.ExecSQL(False);
if Assigned(dbxTransaction) then
_connection.CommitFreeAndNil(dbxTransaction);
Result := True;
except
on Exc:Exception do
begin
if Assigned(dbxTransaction) then
_connection.RollBackFreeAndNil(dbxTransaction);
raise Exc;
Result := False;
end;
end;
finally
if Assigned(dbxTransaction) then
FreeAndNil(dbxTransaction);
end;
end
else
begin
Result := False;
end;
end;
【问题讨论】:
-
Result := False;在raise之后是没用的。如果没有分配Example,我会提出EArgumentNilException,并将其从函数转换为过程 -
在加薪之前分配给结果也是没用的!