TransactionContext (WIP)

This commit is contained in:
Daniele Teti 2024-03-31 18:09:13 +02:00
parent b41e245bbc
commit 4349f20d95
8 changed files with 111 additions and 8 deletions

View File

@ -120,13 +120,16 @@ resourcestring
' end);' + sLineBreak +
'' + sLineBreak +
' WebRequestHandlerProc.MaxConnections := dotEnv.Env(''dmvc.handler.max_connections'', 1024);' + sLineBreak +
'' + sLineBreak +
' if dotEnv.Env(''dmvc.profiler.enabled'', false) then' + sLineBreak +
' begin' + sLineBreak +
' Profiler.ProfileLogger := Log;' + sLineBreak +
' Profiler.WarningThreshold := dotEnv.Env(''dmvc.profiler.warning_threshold'', 2000);' + sLineBreak +
' end;' + sLineBreak +
'' + sLineBreak +
'' + sLineBreak +
'' + sLineBreak +
'{$IF CompilerVersion >= 34}' + sLineBreak +
' if dotEnv.Env(''dmvc.profiler.enabled'', false) then' + sLineBreak +
' begin' + sLineBreak +
' Profiler.ProfileLogger := Log;' + sLineBreak +
' Profiler.WarningThreshold := dotEnv.Env(''dmvc.profiler.warning_threshold'', 2000);' + sLineBreak +
' end;' + sLineBreak +
'{$ENDIF}' + sLineBreak +
'' + sLineBreak +
' RunServer(dotEnv.Env(''dmvc.server.port'', %1:d));' + sLineBreak +
' except' + sLineBreak +
' on E: Exception do' + sLineBreak +

View File

@ -116,7 +116,8 @@ contains
MVCFramework.DotEnv in '..\..\sources\MVCFramework.DotEnv.pas',
MVCFramework.Serializer.URLEncoded in '..\..\sources\MVCFramework.Serializer.URLEncoded.pas',
MVCFramework.Signal in '..\..\sources\MVCFramework.Signal.pas',
MVCFramework.Serializer.Text in '..\..\sources\MVCFramework.Serializer.Text.pas';
MVCFramework.Serializer.Text in '..\..\sources\MVCFramework.Serializer.Text.pas',
MVCFramework.Container in '..\..\sources\MVCFramework.Container.pas';
end.

View File

@ -208,6 +208,7 @@
<DCCReference Include="..\..\sources\MVCFramework.Serializer.URLEncoded.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Signal.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Serializer.Text.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Container.pas"/>
<BuildConfiguration Include="Base">
<Key>Base</Key>
</BuildConfiguration>

View File

@ -319,6 +319,15 @@ object MainForm: TMainForm
TabOrder = 31
OnClick = btnCRUDWithOptionsClick
end
object btnTransaction: TButton
Left = 144
Top = 602
Width = 121
Height = 35
Caption = 'Automatic Transactions'
TabOrder = 32
OnClick = btnTransactionClick
end
object FDConnection1: TFDConnection
Left = 312
Top = 40

View File

@ -27,6 +27,8 @@ uses
FireDAC.Comp.Client,
MVCFramework.Nullables,
MVCFramework.ActiveRecord,
MVCFramework.Logger,
System.Generics.Collections, System.Diagnostics;
type
@ -64,6 +66,7 @@ type
btnObjectVersion: TButton;
btnCustomTable: TButton;
btnCRUDWithOptions: TButton;
btnTransaction: TButton;
procedure btnCRUDClick(Sender: TObject);
procedure btnInheritanceClick(Sender: TObject);
procedure btnMultiThreadingClick(Sender: TObject);
@ -98,6 +101,7 @@ type
procedure btnObjectVersionClick(Sender: TObject);
procedure btnCustomTableClick(Sender: TObject);
procedure btnCRUDWithOptionsClick(Sender: TObject);
procedure btnTransactionClick(Sender: TObject);
private
procedure Log(const Value: string);
procedure LoadCustomers(const HowManyCustomers: Integer = 50);
@ -1896,6 +1900,33 @@ begin
end;
end;
procedure TMainForm.btnTransactionClick(Sender: TObject);
begin
Log('# TransactionContext');
try
begin var Ctx := TMVCActiveRecord.UseTransactionContext;
TMVCActiveRecord.GetByPK<TCustomer>(-1); // will raise EMVCActiveRecordNotFound
end;
except
on E: Exception do
begin
Log('#1 - TransactionContext caught the exception (doing an automatic rollback)');
end;
end;
begin var Ctx := TMVCActiveRecord.UseTransactionContext;
var lCustomer := TCustomer.Create;
try
lCustomer.CompanyName := 'Transaction Inc.';
lCustomer.LastContact := Now();
lCustomer.Insert;
finally
lCustomer.Free;
end;
Log('#2 - TransactionContext automatically committed changes (because no exceptions have been raised within the TransactionContext)');
end;
end;
procedure TMainForm.btnReadOnlyFieldsClick(Sender: TObject);
var
lCustomer: TCustomerWithReadOnlyFields;

View File

@ -26,6 +26,7 @@ unit MVCFramework.ActiveRecord;
{$I dmvcframework.inc}
interface
uses
@ -65,6 +66,16 @@ type
TMVCActiveRecordClass = class of TMVCActiveRecord;
TMVCActiveRecord = class;
{$IF Defined(CUSTOM_MANAGED_RECORDS)}
TMVCTransactionContext = record
private
fConnection: TFDConnection;
public
class operator Finalize(var Dest: TMVCTransactionContext);
class operator Assign (var Dest: TMVCTransactionContext; const [ref] Src: TMVCTransactionContext);
constructor Create(Connection: TFDConnection); overload;
end;
{$ENDIF}
TMVCActiveRecordFieldOption = (
/// <summary>
@ -588,6 +599,9 @@ type
class function All<T: TMVCActiveRecord, constructor>: TObjectList<T>; overload;
class function DeleteRQL<T: TMVCActiveRecord>(const RQL: string = ''): Int64; overload;
class function Count<T: TMVCActiveRecord>(const RQL: string = ''): Int64; overload;
{$IF Defined(CUSTOM_MANAGED_RECORDS)}
class function UseTransactionContext: TMVCTransactionContext;
{$ENDIF}
{ Where }
class function Where<T: TMVCActiveRecord, constructor>(const SQLWhere: string;
@ -2216,6 +2230,13 @@ begin
end;
end;
{$IF Defined(CUSTOM_MANAGED_RECORDS)}
class function TMVCActiveRecordHelper.UseTransactionContext: TMVCTransactionContext;
begin
Result := TMVCTransactionContext.Create(TMVCActiveRecord.CurrentConnection);
end;
{$ENDIF}
class function TMVCActiveRecordHelper.TryGetRQLQuery<T>(
const QueryName: String; out NamedRQLQuery: TRQLQueryWithName): Boolean;
var
@ -4759,6 +4780,38 @@ begin
Create(True);
end;
{ TMVCTransactionContext }
{$IF Defined(CUSTOM_MANAGED_RECORDS)}
constructor TMVCTransactionContext.Create(Connection: TFDConnection);
begin
fConnection := nil;
end;
class operator TMVCTransactionContext.Assign(var Dest: TMVCTransactionContext; const [ref] Src: TMVCTransactionContext);
begin
Dest.fConnection := TMVCActiveRecord.CurrentConnection;
Dest.fConnection.StartTransaction;
end;
class operator TMVCTransactionContext.Finalize(var Dest: TMVCTransactionContext);
begin
if Dest.fConnection <> nil then
begin
if ExceptAddr <> nil then
begin
Dest.fConnection.Rollback;
end
else
begin
Dest.fConnection.Commit;
end;
end;
end;
{$ENDIF}
initialization
gConnectionsLock := TObject.Create;

View File

@ -47,6 +47,7 @@ type
end;
TRegistration = class
public
Intf: TGUID;
Clazz: TClassOfInterfacedObject;
RttiType: TRttiType;

View File

@ -100,3 +100,7 @@ DelphiMVCFramework is compatible with Delphi version XE7 or better
{$ENDIF}
{$DEFINE USEFIREDAC}
{$IF Defined(SYDNEYORBETTER)}
{$DEFINE CUSTOM_MANAGED_RECORDS}
{$ENDIF}