foVersion (WIP + new sample)

This commit is contained in:
Daniele Teti 2023-11-27 18:11:49 +01:00
parent 3a748821ce
commit e0190b3fe8
12 changed files with 1536 additions and 15 deletions

View File

@ -140,6 +140,34 @@ type
property Price: UInt32 read FPrice write SetPrice; property Price: UInt32 read FPrice write SetPrice;
end; end;
[MVCNameCase(ncLowerCase)]
[MVCTable('customers_with_version')]
TCustomersWithVersion = class(TMVCActiveRecord)
private
[MVCTableField('id', [foPrimaryKey, foAutoGenerated])]
fID: Int64;
[MVCTableField('code')]
fCode: NullableString;
[MVCTableField('description')]
fDescription: NullableString;
[MVCTableField('city')]
fCity: NullableString;
[MVCTableField('note')]
fNote: NullableString;
[MVCTableField('rating')]
fRating: NullableInt32;
[MVCTableField('objversion', [foVersion])]
fObjversion: Integer;
public
property ID: Int64 read fID write fID;
property Code: NullableString read fCode write fCode;
property Description: NullableString read fDescription write fDescription;
property City: NullableString read fCity write fCity;
property Note: NullableString read fNote write fNote;
property Rating: NullableInt32 read fRating write fRating;
property ObjVersion: Integer read fObjversion write fObjversion;
end;
implementation implementation
uses uses
@ -310,6 +338,7 @@ ActiveRecordMappingRegistry.AddEntity('salary', TSalaryAggregate);
ActiveRecordMappingRegistry.AddEntity('contacts', TContact); ActiveRecordMappingRegistry.AddEntity('contacts', TContact);
ActiveRecordMappingRegistry.AddEntity('phones', TPhone); ActiveRecordMappingRegistry.AddEntity('phones', TPhone);
ActiveRecordMappingRegistry.AddEntity('articles', TArticle); ActiveRecordMappingRegistry.AddEntity('articles', TArticle);
ActiveRecordMappingRegistry.AddEntity('customers', TCustomersWithVersion);
finalization finalization

View File

@ -41,7 +41,6 @@ type
var var
WebModuleClass: TComponentClass = TMyWebModule; WebModuleClass: TComponentClass = TMyWebModule;
ConnectionDefinitionName: string = '';
implementation implementation
@ -82,7 +81,7 @@ begin
FMVC.AddController(TMVCActiveRecordController, FMVC.AddController(TMVCActiveRecordController,
function: TMVCController function: TMVCController
begin begin
Result := TMVCActiveRecordController.Create(ConnectionDefinitionName); Result := TMVCActiveRecordController.Create(CON_DEF_NAME);
end, '/api/entities'); end, '/api/entities');
end; end;

View File

@ -36,7 +36,6 @@ var
lServer: TIdHTTPWebBrokerBridge; lServer: TIdHTTPWebBrokerBridge;
lCmd: string; lCmd: string;
begin begin
ConnectionDefinitionName := CON_DEF_NAME;
Writeln('** DMVCFramework Server ** build ' + DMVCFRAMEWORK_VERSION); Writeln('** DMVCFramework Server ** build ' + DMVCFRAMEWORK_VERSION);
if ParamCount >= 1 then if ParamCount >= 1 then
lCmd := ParamStr(1) lCmd := ParamStr(1)

View File

@ -7,7 +7,7 @@
<TargetedPlatforms>32897</TargetedPlatforms> <TargetedPlatforms>32897</TargetedPlatforms>
<AppType>Console</AppType> <AppType>Console</AppType>
<FrameworkType>None</FrameworkType> <FrameworkType>None</FrameworkType>
<ProjectVersion>19.5</ProjectVersion> <ProjectVersion>20.1</ProjectVersion>
<Platform Condition="'$(Platform)'==''">Win32</Platform> <Platform Condition="'$(Platform)'==''">Win32</Platform>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''"> <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
@ -286,6 +286,16 @@
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="AndroidSplashImageDefV21">
<Platform Name="Android">
<RemoteDir>res\drawable-anydpi-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-anydpi-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashStyles"> <DeployClass Name="AndroidSplashStyles">
<Platform Name="Android"> <Platform Name="Android">
<RemoteDir>res\values</RemoteDir> <RemoteDir>res\values</RemoteDir>
@ -306,6 +316,66 @@
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="AndroidSplashStylesV31">
<Platform Name="Android">
<RemoteDir>res\values-v31</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\values-v31</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_AdaptiveIcon">
<Platform Name="Android">
<RemoteDir>res\drawable-anydpi-v26</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-anydpi-v26</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_AdaptiveIconBackground">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_AdaptiveIconForeground">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_AdaptiveIconMonochrome">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_AdaptiveIconV33">
<Platform Name="Android">
<RemoteDir>res\drawable-anydpi-v33</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-anydpi-v33</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_Colors"> <DeployClass Name="Android_Colors">
<Platform Name="Android"> <Platform Name="Android">
<RemoteDir>res\values</RemoteDir> <RemoteDir>res\values</RemoteDir>
@ -316,6 +386,16 @@
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="Android_ColorsDark">
<Platform Name="Android">
<RemoteDir>res\values-night-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\values-night-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_DefaultAppIcon"> <DeployClass Name="Android_DefaultAppIcon">
<Platform Name="Android"> <Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir> <RemoteDir>res\drawable</RemoteDir>
@ -486,6 +566,56 @@
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="Android_VectorizedNotificationIcon">
<Platform Name="Android">
<RemoteDir>res\drawable-anydpi-v24</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-anydpi-v24</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_VectorizedSplash">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_VectorizedSplashDark">
<Platform Name="Android">
<RemoteDir>res\drawable-night-anydpi-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-night-anydpi-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_VectorizedSplashV31">
<Platform Name="Android">
<RemoteDir>res\drawable-anydpi-v31</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-anydpi-v31</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_VectorizedSplashV31Dark">
<Platform Name="Android">
<RemoteDir>res\drawable-night-anydpi-v31</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-night-anydpi-v31</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DebugSymbols"> <DeployClass Name="DebugSymbols">
<Platform Name="iOSSimulator"> <Platform Name="iOSSimulator">
<Operation>1</Operation> <Operation>1</Operation>

View File

@ -0,0 +1,90 @@
unit CustomersControllerU;
interface
uses
MVCFramework,
MVCFramework.ActiveRecord,
MVCFramework.Commons,
System.Generics.Collections,
EntitiesU;
type
[MVCPath('/api/customers')]
TCustomersController = class(TMVCController)
public
[MVCPath]
[MVCHTTPMethods([httpGET])]
procedure GetCustomers([MVCFromQueryString('rql','')] RQLFilter: String);
[MVCPath('/($ID)')]
[MVCHTTPMethods([httpGET])]
procedure GetCustomerByID(const ID: Integer);
[MVCPath('/($ID)')]
[MVCHTTPMethods([httpPUT])]
procedure UpdateCustomerByID(const [MVCFromBody] Customer: TCustomer; const ID: Integer);
[MVCPath]
[MVCHTTPMethods([httpPOST])]
procedure CreateCustomer([MVCFromBody] const Customer: TCustomer);
[MVCPath('/_bulk')]
[MVCHTTPMethods([httpPOST])]
procedure BulkCreateCustomers([MVCFromBody] const Customers: TObjectList<TCustomer>);
end;
implementation
uses
System.SysUtils,
FireDAC.Comp.Client,
FireDAC.Stan.Param,
MVCFramework.Logger,
MVCFramework.Serializer.Commons,
JsonDataObjects;
{ TCustomersController }
procedure TCustomersController.CreateCustomer(const Customer: TCustomer);
begin
Customer.Insert;
Render201Created('/api/customers/' + Customer.ID.Value.ToString);
end;
procedure TCustomersController.GetCustomerByID(const ID: Integer);
begin
Render(ObjectDict().Add('data', TMVCActiveRecord.GetByPK<TCustomer>(ID)));
end;
procedure TCustomersController.GetCustomers([MVCFromQueryString('rql','')] RQLFilter: String);
begin
if RQLFilter.IsEmpty then
Render(ObjectDict().Add('data', TMVCActiveRecord.All<TCustomer>))
else
Render(ObjectDict().Add('data', TMVCActiveRecord.SelectRQL<TCustomer>(RQLFilter, 1000)));
end;
procedure TCustomersController.UpdateCustomerByID(const Customer: TCustomer; const ID: Integer);
begin
Customer.ID := ID;
Customer.Update();
end;
procedure TCustomersController.BulkCreateCustomers(const Customers: TObjectList<TCustomer>);
begin
TMVCActiveRecord.CurrentConnection.StartTransaction;
try
for var lCustomer in Customers do
begin
lCustomer.Insert;
end;
TMVCActiveRecord.CurrentConnection.Commit;
Render201Created();
except
TMVCActiveRecord.CurrentConnection.Rollback;
end;
end;
end.

View File

@ -0,0 +1,70 @@
// *************************************************************************** }
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2023 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//
// ***************************************************************************
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// ***************************************************************************
unit EntitiesU;
interface
uses
MVCFramework.Serializer.Commons,
MVCFramework.ActiveRecord,
MVCFramework.SQLGenerators.PostgreSQL,
System.Generics.Collections,
System.Classes,
FireDAC.Stan.Param,
MVCFramework.Nullables;
type
[MVCNameCase(ncLowerCase)]
[MVCTable('customers_with_version')]
TCustomer = class(TMVCActiveRecord)
private
[MVCTableField('id', [foPrimaryKey, foAutoGenerated])]
fID: NullableInt64;
[MVCTableField('code')]
fCode: NullableString;
[MVCTableField('description')]
fCompanyName: NullableString;
[MVCTableField('city')]
fCity: string;
[MVCTableField('rating')]
fRating: NullableInt32;
[MVCTableField('note')]
fNote: string;
[MVCTableField('objversion', [foVersion])]
fObjVersion: Integer;
public
property ID: NullableInt64 read fID write fID;
property Code: NullableString read fCode write fCode;
property CompanyName: NullableString read fCompanyName write fCompanyName;
property City: string read fCity write fCity;
property Rating: NullableInt32 read fRating write fRating;
property Note: string read fNote write fNote;
property ObjVersion: Integer read fObjVersion;
end;
implementation
end.

View File

@ -0,0 +1,8 @@
object TMunicipalLibraryWebModule: TTMunicipalLibraryWebModule
OldCreateOrder = False
OnCreate = WebModuleCreate
OnDestroy = WebModuleDestroy
Actions = <>
Height = 230
Width = 415
end

View File

@ -0,0 +1,71 @@
unit MainWM;
interface
uses
System.SysUtils,
System.Classes,
Web.HTTPApp,
MVCFramework;
type
TTMunicipalLibraryWebModule = class(TWebModule)
procedure WebModuleCreate(Sender: TObject);
procedure WebModuleDestroy(Sender: TObject);
private
FMVC: TMVCEngine;
public
{ Public declarations }
end;
var
WebModuleClass: TComponentClass = TTMunicipalLibraryWebModule;
implementation
{$R *.dfm}
uses
CustomersControllerU,
MVCFramework.Middleware.ActiveRecord,
System.IOUtils,
MVCFramework.Commons,
MVCFramework.Middleware.Compression;
procedure TTMunicipalLibraryWebModule.WebModuleCreate(Sender: TObject);
begin
FMVC := TMVCEngine.Create(Self,
procedure(Config: TMVCConfig)
begin
// session timeout (0 means session cookie)
Config[TMVCConfigKey.SessionTimeout] := '0';
// default content-type
Config[TMVCConfigKey.DefaultContentType] := TMVCConstants.DEFAULT_CONTENT_TYPE;
// default content charset
Config[TMVCConfigKey.DefaultContentCharset] := TMVCConstants.DEFAULT_CONTENT_CHARSET;
// unhandled actions are permitted?
Config[TMVCConfigKey.AllowUnhandledAction] := 'false';
// default view file extension
Config[TMVCConfigKey.DefaultViewFileExtension] := 'html';
// view path
Config[TMVCConfigKey.ViewPath] := 'templates';
// Max Record Count for automatic Entities CRUD
Config[TMVCConfigKey.MaxEntitiesRecordCount] := '20';
// Enable Server Signature in response
Config[TMVCConfigKey.ExposeServerSignature] := 'true';
// Max request size in bytes
Config[TMVCConfigKey.MaxRequestSize] := IntToStr(TMVCConstants.DEFAULT_MAX_REQUEST_SIZE);
end);
FMVC.AddController(TCustomersController);
// To enable compression (deflate, gzip) just add this middleware as the last one
FMVC.AddMiddleware(TMVCActiveRecordMiddleware.Create('activerecorddb'));
FMVC.AddMiddleware(TMVCCompressionMiddleware.Create);
end;
procedure TTMunicipalLibraryWebModule.WebModuleDestroy(Sender: TObject);
begin
FMVC.Free;
end;
end.

View File

@ -0,0 +1,63 @@
program SimpleVersionedRESTAPIUsingActiveRecord;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
MVCFramework,
MVCFramework.Logger,
MVCFramework.Commons,
MVCFramework.Signal,
Web.ReqMulti,
Web.WebReq,
Web.WebBroker,
IdContext,
IdHTTPWebBrokerBridge,
CustomersControllerU in 'CustomersControllerU.pas',
MainWM in 'MainWM.pas' {TMunicipalLibraryWebModule: TWebModule},
EntitiesU in 'EntitiesU.pas';
{$R *.res}
procedure RunServer(APort: Integer);
var
LServer: TIdHTTPWebBrokerBridge;
begin
Writeln('** DMVCFramework Server ** build ' + DMVCFRAMEWORK_VERSION);
LServer := TIdHTTPWebBrokerBridge.Create(nil);
try
LServer.OnParseAuthentication := TMVCParseAuthentication.OnParseAuthentication;
LServer.DefaultPort := APort;
{ more info about MaxConnections
http://www.indyproject.org/docsite/html/frames.html?frmname=topic&frmfile=TIdCustomTCPServer_MaxConnections.html }
LServer.MaxConnections := 0;
{ more info about ListenQueue
http://www.indyproject.org/docsite/html/frames.html?frmname=topic&frmfile=TIdCustomTCPServer_ListenQueue.html }
LServer.ListenQueue := 200;
LServer.Active := True;
Writeln('Listening on port ', APort);
Writeln('CTRL+C to shutdown the server');
WaitForTerminationSignal;
EnterInShutdownState;
finally
LServer.Free;
end;
end;
begin
ReportMemoryLeaksOnShutdown := True;
IsMultiThread := True;
try
if WebRequestHandler <> nil then
WebRequestHandler.WebModuleClass := WebModuleClass;
WebRequestHandlerProc.MaxConnections := 1024;
RunServer(8080);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.

View File

@ -58,6 +58,10 @@ type
procedure AfterConstruction; override; procedure AfterConstruction; override;
end; end;
EMVCActiveRecordVersionedItemNotFound = class(EMVCActiveRecordNotFound)
end;
TMVCActiveRecordClass = class of TMVCActiveRecord; TMVCActiveRecordClass = class of TMVCActiveRecord;
TMVCActiveRecord = class; TMVCActiveRecord = class;
TMVCActiveRecordFieldOption = (foPrimaryKey, { it's the primary key of the mapped table } TMVCActiveRecordFieldOption = (foPrimaryKey, { it's the primary key of the mapped table }
@ -214,11 +218,13 @@ type
end; end;
TMVCTableMap = class TMVCTableMap = class
private
fVersionRTTIField: TRttiField;
fVersionFieldName: String;
public public
fPartitionInfoInternal: TPartitionInfo; fPartitionInfoInternal: TPartitionInfo;
fEntityAllowedActions: TMVCEntityActions; fEntityAllowedActions: TMVCEntityActions;
fTableName: String; fTableName: String;
fVersionFieldName: String;
fIsVersioned: Boolean; fIsVersioned: Boolean;
fPartitionClause: String; fPartitionClause: String;
fRTTIType: TRttiInstanceType; fRTTIType: TRttiInstanceType;
@ -226,7 +232,6 @@ type
fDefaultRQLFilter: string; fDefaultRQLFilter: string;
fMap: TFieldsMap; fMap: TFieldsMap;
fPrimaryKey: TRTTIField; fPrimaryKey: TRTTIField;
fVersionRTTIField: TRttiField;
fMapping: TMVCFieldsMapping; fMapping: TMVCFieldsMapping;
fPropsAttributes: TArray<TCustomAttribute>; fPropsAttributes: TArray<TCustomAttribute>;
fProps: TArray<TRTTIField>; fProps: TArray<TRTTIField>;
@ -239,6 +244,7 @@ type
public public
constructor Create; constructor Create;
destructor Destroy; override; destructor Destroy; override;
function VersionValueAsInt64For(AR: TMVCActiveRecord): Int64; //inline;
end; end;
TMVCActiveRecord = class TMVCActiveRecord = class
@ -2228,8 +2234,8 @@ begin
begin begin
if fTableMap.fIsVersioned then if fTableMap.fIsVersioned then
begin begin
raise EMVCActiveRecordNotFound.CreateFmt('No record deleted for key [Entity: %s][PK: %s][Version: %d]', raise EMVCActiveRecordVersionedItemNotFound.CreateFmt('No record deleted for key [Entity: %s][PK: %s][Version: %d] - record or version not found',
[ClassName, fTableMap.fPrimaryKeyFieldName, fTableMap.fVersionRTTIField.GetValue(Self).AsInt64]); [ClassName, fTableMap.fPrimaryKeyFieldName, fTableMap.VersionValueAsInt64For(Self)]);
end end
else else
begin begin
@ -3497,8 +3503,8 @@ begin
begin begin
if fTableMap.fIsVersioned then if fTableMap.fIsVersioned then
begin begin
raise EMVCActiveRecordNotFound.CreateFmt('No record updated for key [Entity: %s][PK: %s][Version: %d]', raise EMVCActiveRecordVersionedItemNotFound.CreateFmt('No record updated for key [Entity: %s][PK: %s][Version: %d] - record or version not found',
[ClassName, fTableMap.fPrimaryKeyFieldName, fTableMap.fVersionRTTIField.GetValue(Self).AsInt64]); [ClassName, fTableMap.fPrimaryKeyFieldName, fTableMap.VersionValueAsInt64For(Self)]);
end end
else else
begin begin
@ -3557,7 +3563,7 @@ procedure TMVCActiveRecord.AdvanceVersioning(const TableMap: TMVCTableMap; const
var var
lCurrVersion: Int64; lCurrVersion: Int64;
begin begin
lCurrVersion := TableMap.fVersionRTTIField.GetValue(ARInstance).AsInt64; lCurrVersion := TableMap.VersionValueAsInt64For(ARInstance);
Inc(lCurrVersion); Inc(lCurrVersion);
TableMap.fVersionRTTIField.SetValue(ARInstance, lCurrVersion); TableMap.fVersionRTTIField.SetValue(ARInstance, lCurrVersion);
end; end;
@ -3845,7 +3851,7 @@ begin
GetParamNameForSQL(TableMap.fPrimaryKeyFieldName); GetParamNameForSQL(TableMap.fPrimaryKeyFieldName);
if TableMap.fIsVersioned then if TableMap.fIsVersioned then
begin begin
Result := Result + ' and ' + GetFieldNameForSQL(TableMap.fVersionFieldName) + ' = ' + IntToStr(TableMap.fVersionRTTIField.GetValue(ARInstance).AsInt64); Result := Result + ' and ' + GetFieldNameForSQL(TableMap.fVersionFieldName) + ' = ' + IntToStr(TableMap.VersionValueAsInt64For(ARInstance));
end; end;
end; end;
@ -3891,7 +3897,7 @@ begin
begin begin
if lPair.Value.IsVersion then if lPair.Value.IsVersion then
begin begin
Result := Result + GetFieldNameForSQL(lPair.Value.FieldName) + ' = :' + Result := Result + GetFieldNameForSQL(lPair.Value.FieldName) + ' = ' +
GetParamNameForSQL(lPair.Value.FieldName) + ' + 1,'; GetParamNameForSQL(lPair.Value.FieldName) + ' + 1,';
end else if lPair.Value.Writeable then end else if lPair.Value.Writeable then
begin begin
@ -3913,7 +3919,8 @@ begin
GetFieldNameForSQL(TableMap.fPrimaryKeyFieldName) + '= :' + GetParamNameForSQL(TableMap.fPrimaryKeyFieldName); GetFieldNameForSQL(TableMap.fPrimaryKeyFieldName) + '= :' + GetParamNameForSQL(TableMap.fPrimaryKeyFieldName);
if TableMap.fIsVersioned then if TableMap.fIsVersioned then
begin begin
Result := Result + ' and ' + GetFieldNameForSQL(TableMap.fVersionFieldName) + ' = ' + TableMap.fVersionRTTIField.GetValue(ARInstance).AsInt64.ToString Result := Result + ' and ' + GetFieldNameForSQL(TableMap.fVersionFieldName) +
' = ' + TableMap.VersionValueAsInt64For(ARInstance).ToString
end; end;
end end
else else
@ -4617,6 +4624,11 @@ begin
inherited; inherited;
end; end;
function TMVCTableMap.VersionValueAsInt64For(AR: TMVCActiveRecord): Int64;
begin
Result := fVersionRTTIField.GetValue(AR).AsInt64;
end;
class function TMVCActiveRecordHelper.Select( class function TMVCActiveRecordHelper.Select(
const aClass: TMVCActiveRecordClass; const aClass: TMVCActiveRecordClass;
const SQL: string; const Params: array of Variant; const SQL: string; const Params: array of Variant;

View File

@ -85,7 +85,6 @@ begin
for lKeyValue in TableMap.fMap do for lKeyValue in TableMap.fMap do
begin begin
// if not(foTransient in lKeyValue.Value.FieldOptions) then
if lKeyValue.Value.Writeable then if lKeyValue.Value.Writeable then
begin begin
lSB.Append(GetFieldNameForSQL(lKeyValue.Value.FieldName) + ','); lSB.Append(GetFieldNameForSQL(lKeyValue.Value.FieldName) + ',');