// *************************************************************************** } // // Delphi MVC Framework // // Copyright (c) 2010-2020 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; {$RTTI EXPLICIT METHODS([vcPublic, vcPublished]) FIELDS([vcPrivate, vcProtected, vcPublic, vcPublished]) PROPERTIES([vcPublic, vcPublished])} interface uses MVCFramework.Serializer.Commons, MVCFramework.ActiveRecord, System.Generics.Collections, System.Classes, FireDAC.Stan.Param, MVCFramework.Nullables; type TCustomEntity = class abstract(TMVCActiveRecord) protected procedure OnBeforeExecuteSQL(var SQL: string); override; end; [MVCNameCase(ncLowerCase)] [MVCTable('articles')] TArticle = class(TCustomEntity) private [MVCTableField('ID')] fID: NullableInt32; [MVCTableField('code')] fCodice: NullableString; [MVCTableField('description')] fDescrizione: string; [MVCTableField('price')] fPrezzo: Currency; public constructor Create; override; destructor Destroy; override; property ID: NullableInt32 read fID write fID; property Code: NullableString read fCodice write fCodice; property Description: string read fDescrizione write fDescrizione; property Price: Currency read fPrezzo write fPrezzo; end; TOrder = class; [MVCNameCase(ncLowerCase)] [MVCTable('customers')] TCustomer = class(TCustomEntity) private {$IFNDEF USE_SEQUENCES} [MVCTableField('id', [foPrimaryKey, foAutoGenerated])] {$ELSE} [MVCTableField('id', [foPrimaryKey, foAutoGenerated], 'SEQ_CUSTOMERS_ID' { required for interbase } )] {$ENDIF} fID: NullableInt64; [MVCTableField('code')] fCode: NullableString; [MVCTableField('description')] fCompanyName: NullableString; [MVCTableField('city')] fCity: string; [MVCTableField('rating')] fRating: NullableInt32; [MVCTableField('note')] fNote: string; public constructor Create; override; destructor Destroy; override; 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; end; [MVCNameCase(ncLowerCase)] [MVCTable('customers')] TCustomerWithTransient = class(TCustomEntity) private {$IFNDEF USE_SEQUENCES} [MVCTableField('id', [foPrimaryKey, foAutoGenerated])] {$ELSE} [MVCTableField('id', [foPrimaryKey, foAutoGenerated], 'SEQ_CUSTOMERS_ID' { required for interbase } )] {$ENDIF} fID: Integer; [MVCTableField('code', [foTransient])] fCode: string; [MVCTableField('', [foTransient])] fFormattedCode: string; [MVCTableField('description')] fCompanyName: string; [MVCTableField('city')] fCity: string; procedure SetFormattedCode(const Value: string); public property ID: Integer read fID write fID; property Code: string read fCode write fCode; property FormattedCode: string read fFormattedCode write SetFormattedCode; property CompanyName: string read fCompanyName write fCompanyName; property City: string read fCity write fCity; end; [MVCNameCase(ncLowerCase)] [MVCTable('order_details')] TOrderDetail = class(TCustomEntity) private {$IFNDEF USE_SEQUENCES} [MVCTableField('id', [foPrimaryKey, foAutoGenerated])] {$ELSE} [MVCTableField('id', [foPrimaryKey, foAutoGenerated], 'SEQ_order_details_ID' { required for interbase } )] {$ENDIF} fID: Integer; [MVCTableField('id_order')] fOrderID: Integer; [MVCTableField('id_article')] fArticleID: Integer; [MVCTableField('unit_price')] fPrice: Currency; [MVCTableField('discount')] fDiscount: Integer; [MVCTableField('quantity')] fQuantity: Integer; [MVCTableField('description')] fDescription: string; [MVCTableField('total')] fTotal: Currency; public constructor Create; override; destructor Destroy; override; property ID: Integer read fID write fID; property OrderID: Integer read fOrderID write fOrderID; property ArticleID: Integer read fArticleID write fArticleID; property Price: Currency read fPrice write fPrice; property Discount: Integer read fDiscount write fDiscount; property Quantity: Integer read fQuantity write fQuantity; property Description: string read fDescription write fDescription; property Total: Currency read fTotal write fTotal; end; [MVCNameCase(ncLowerCase)] [MVCTable('customers_plain')] TCustomerPlain = class(TCustomEntity) private [MVCTableField('id', [foPrimaryKey])] fID: NullableInt64; [MVCTableField('code')] fCode: NullableString; [MVCTableField('description')] fCompanyName: NullableString; [MVCTableField('city')] fCity: string; [MVCTableField('rating')] fRating: NullableInt32; [MVCTableField('note')] fNote: string; 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; end; [MVCNameCase(ncLowerCase)] [MVCTable('customers with spaces')] TCustomerWithSpaces = class(TCustomEntity) private [MVCTableField('id with spaces', [foPrimaryKey])] fID: NullableInt64; [MVCTableField('code with spaces')] fCode: NullableString; [MVCTableField('description with spaces')] fCompanyName: NullableString; [MVCTableField('city with spaces')] fCity: string; [MVCTableField('rating with spaces')] fRating: NullableInt32; [MVCTableField('note with spaces')] fNote: string; 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; end; [MVCNameCase(ncLowerCase)] [MVCTable('customers_with_code')] TCustomerWithCode = class(TCustomEntity) private [MVCTableField('code', [foPrimaryKey])] fCode: NullableString; [MVCTableField('description')] fCompanyName: NullableString; [MVCTableField('city')] fCity: string; [MVCTableField('rating')] fRating: NullableInt32; [MVCTableField('note')] fNote: string; public 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; end; [MVCNameCase(ncLowerCase)] [MVCTable('orders')] TOrder = class(TCustomEntity) private {$IFNDEF USE_SEQUENCES} [MVCTableField('id', [foPrimaryKey, foAutoGenerated])] {$ELSE} [MVCTableField('id', [foPrimaryKey, foAutoGenerated], 'SEQ_ORDERS_ID' { required for interbase } )] {$ENDIF} fID: Integer; [MVCTableField('id_customer')] fCustomerID: Integer; [MVCTableField('order_date')] fOrderDate: TDate; [MVCTableField('total')] fTotal: Currency; public constructor Create; override; destructor Destroy; override; property ID: Integer read fID write fID; property CustomerID: Integer read fCustomerID write fCustomerID; property OrderDate: TDate read fOrderDate write fOrderDate; property Total: Currency read fTotal write fTotal; end; [MVCNameCase(ncLowerCase)] [MVCTable('customers')] TCustomerEx = class(TCustomer) private fOrders: TObjectList; function GetOrders: TObjectList; protected procedure OnAfterLoad; override; procedure OnAfterInsert; override; public destructor Destroy; override; property Orders: TObjectList read GetOrders; end; [MVCNameCase(ncLowerCase)] [MVCTable('customers')] TCustomerWithLogic = class(TCustomer) private fIsLocatedInRome: Boolean; protected procedure OnAfterLoad; override; procedure OnBeforeInsertOrUpdate; override; procedure OnValidation(const Action: TMVCEntityAction); override; public property IsLocatedInRome: Boolean read fIsLocatedInRome; end; [MVCNameCase(ncLowerCase)] [MVCTable('nullables_test')] TNullablesTest = class(TCustomEntity) private [MVCTableField('f_int2')] ff_int2: NullableInt16; [MVCTableField('f_int4')] ff_int4: NullableInt32; [MVCTableField('f_int8')] ff_int8: NullableInt64; [MVCTableField('f_date')] ff_date: NullableTDate; [MVCTableField('f_time')] ff_time: NullableTTime; [MVCTableField('f_bool')] ff_bool: NullableBoolean; [MVCTableField('f_datetime')] ff_datetime: NullableTDateTime; [MVCTableField('f_float4')] ff_float4: NullableSingle; [MVCTableField('f_float8')] ff_float8: NullableDouble; [MVCTableField('f_string')] ff_string: NullableString; [MVCTableField('f_currency')] ff_currency: NullableCurrency; [MVCTableField('f_blob')] ff_blob: TStream; public constructor Create; override; destructor Destroy; override; // f_int2 int2 NULL, property f_int2: NullableInt16 read ff_int2 write ff_int2; // f_int4 int4 NULL, property f_int4: NullableInt32 read ff_int4 write ff_int4; // f_int8 int8 NULL, property f_int8: NullableInt64 read ff_int8 write ff_int8; // f_string varchar NULL, property f_string: NullableString read ff_string write ff_string; // f_bool bool NULL, property f_bool: NullableBoolean read ff_bool write ff_bool; // f_date date NULL, property f_date: NullableTDate read ff_date write ff_date; // f_time time NULL, property f_time: NullableTTime read ff_time write ff_time; // f_datetime timestamp NULL, property f_datetime: NullableTDateTime read ff_datetime write ff_datetime; // f_float4 float4 NULL, property f_float4: NullableSingle read ff_float4 write ff_float4; // f_float8 float8 NULL, property f_float8: NullableDouble read ff_float8 write ff_float8; // f_currency numeric(18,4) NULL property f_currency: NullableCurrency read ff_currency write ff_currency; // f_blob bytea NULL property f_blob: TStream read ff_blob write ff_blob; end; implementation uses System.SysUtils, Data.DB, MVCFramework.Logger; constructor TArticle.Create; begin inherited Create; end; destructor TArticle.Destroy; begin inherited; end; constructor TCustomer.Create; begin inherited Create; end; destructor TCustomer.Destroy; begin inherited; end; constructor TOrderDetail.Create; begin inherited Create; end; destructor TOrderDetail.Destroy; begin inherited; end; constructor TOrder.Create; begin inherited Create; end; destructor TOrder.Destroy; begin inherited; end; { TCustomerEx } destructor TCustomerEx.Destroy; begin fOrders.Free; inherited; end; function TCustomerEx.GetOrders: TObjectList; begin if not Assigned(fOrders) then begin fOrders := TObjectList.Create(True); end; Result := fOrders; end; procedure TCustomerEx.OnAfterInsert; begin inherited; end; procedure TCustomerEx.OnAfterLoad; begin inherited; if Self.ID.HasValue then begin fOrders.Free; fOrders := TMVCActiveRecord.Where('id_customer = ?', [Self.ID]); end; end; { TCustomerWithLogic } procedure TCustomerWithLogic.OnAfterLoad; begin inherited; fIsLocatedInRome := fCity = 'ROME'; end; procedure TCustomerWithLogic.OnBeforeInsertOrUpdate; begin inherited; fCompanyName := fCompanyName.ValueOrDefault.ToUpper; fCity := fCity.ToUpper; end; procedure TCustomerWithLogic.OnValidation(const Action: TMVCEntityAction); begin inherited; if fCompanyName.ValueOrDefault.IsEmpty or fCity.Trim.IsEmpty or fCode.Value.Trim.IsEmpty then raise Exception.Create('CompanyName, City and Code are required'); end; { TCustomerWithTransient } procedure TCustomerWithTransient.SetFormattedCode(const Value: string); begin fFormattedCode := Value; end; { TNullablesTest } constructor TNullablesTest.Create; begin inherited Create; // ff_blob := TMemoryStream.Create; end; destructor TNullablesTest.Destroy; begin ff_blob.Free; inherited; end; { TCustomEntity } procedure TCustomEntity.OnBeforeExecuteSQL(var SQL: string); begin inherited; Log.Info(ClassName + ' | ' + SQL, 'sql_trace'); end; end.