背景
我的应用程序随机地有只读事务错误,在调试之后,我意识到连接显然保留了上次创建的事务的设置。
这应该是Firedac/PostgreSQL的预期行为,还是它有可能是一个bug?
代码
我能够在一个高度简化的、孤立的代码版本中重现该行为:
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
FireDAC.Comp.Client,
FireDAC.DApt,
FireDAC.Phys.PG,
FireDAC.Phys.PGDef,
FireDAC.Stan.Async,
FireDAC.Stan.Def,
FireDAC.Stan.Intf,
System.SysUtils;
var
LConnectionDef: IFDStanConnectionDef;
LQueryRO: TFDQuery;
LQueryRW: TFDQuery;
LTransactionRO: TFDTransaction;
LTransactionRW: TFDTransaction;
LConnection: TFDCustomConnection;
begin
try
FDManager.DriverDefFileAutoLoad := False;
FDManager.ConnectionDefs.AutoLoad := False;
FDManager.ConnectionDefs.Clear;
FDManager.ConnectionDefs.BeginWrite;
try
LConnectionDef := FDManager.ConnectionDefs.AddConnectionDef;
LConnectionDef.Name := 'MY_DB';
with TFDPhysPGConnectionDefParams(LConnectionDef.Params) do
begin
DriverID := 'PG';
CharacterSet := TFDPGCharacterSet.csUTF8;
Server := '127.0.0.1';
Database := 'public';
Port := 11786;
UserName := 'my_user';
Password := '123456';
end;
finally
FDManager.ConnectionDefs.EndWrite;
end;
LConnection := FDManager.AcquireConnection('MY_DB', '');
LTransactionRO := TFDTransaction.Create(nil);
LQueryRO := TFDQuery.Create(nil);
try
LTransactionRO.Connection := LConnection;
LTransactionRO.Options.ReadOnly := True;
LQueryRO.Connection := LConnection;
LQueryRO.Transaction := LTransactionRO;
LQueryRO.Open('SELECT * FROM MY_TABLE');
finally
LQueryRO.Free;
LTransactionRO.Free;
end;
LTransactionRW := TFDTransaction.Create(nil);
LQueryRW := TFDQuery.Create(nil);
try
LTransactionRW.Connection := LConnection;
LTransactionRW.Options.ReadOnly := False;
LQueryRW.Connection := LConnection;
LQueryRW.Transaction := LTransactionRW;
//ERROR: cannot execute UPDATE in a read-only transaction.
LQueryRW.ExecSQL('UPDATE MY_TABLE SET COLUMN_1 = COLUMN_1 WHERE 1=1');
finally
LQueryRW.Free;
LTransactionRW.Free;
end;
Writeln('OK');
Readln;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
**注1:**如果我注解了LTransactionRO.Options.ReadOnly := True;
行,UPDATE SQL
运行时没有错误。
**注2:**我正在 Delphi Alexandria 进行测试
1条答案
按热度按时间cclgggtu1#
如文档FireDAC.Stan.Option.TFDTxOptions.ReadOnly中所述
使用ReadOnly属性值通知DBMS事务只读取数据,但不修改数据。默认值为False。将ReadOnly属性设置为True允许DBMS优化资源使用。
不修改当前事务。最好明确指定StartTransaction、Commit、Rollback。
释放TFDQuery不会自动关闭事务。