mirror of
https://github.com/danieleteti/delphimvcframework.git
synced 2024-11-15 15:55:54 +01:00
foVersion (WIP + new sample)
This commit is contained in:
parent
3a748821ce
commit
e0190b3fe8
@ -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
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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>
|
||||||
|
@ -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.
|
@ -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.
|
@ -0,0 +1,8 @@
|
|||||||
|
object TMunicipalLibraryWebModule: TTMunicipalLibraryWebModule
|
||||||
|
OldCreateOrder = False
|
||||||
|
OnCreate = WebModuleCreate
|
||||||
|
OnDestroy = WebModuleDestroy
|
||||||
|
Actions = <>
|
||||||
|
Height = 230
|
||||||
|
Width = 415
|
||||||
|
end
|
@ -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.
|
@ -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.
|
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||||
|
@ -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) + ',');
|
||||||
|
Loading…
Reference in New Issue
Block a user