mirror of
https://github.com/danieleteti/delphimvcframework.git
synced 2024-11-15 07:45:54 +01:00
+ added more unit test for TMVCActiveRecord.Merge method
This commit is contained in:
parent
0927e3c449
commit
e3eb26e04a
1
.gitignore
vendored
1
.gitignore
vendored
@ -114,3 +114,4 @@ samples/data/activerecorddb.sql
|
|||||||
samples/data/dump.sql
|
samples/data/dump.sql
|
||||||
samples/activerecord_showcase/activerecord_showcase.delphilsp.json
|
samples/activerecord_showcase/activerecord_showcase.delphilsp.json
|
||||||
unittests/general/TestServer/TestServer.delphilsp.json
|
unittests/general/TestServer/TestServer.delphilsp.json
|
||||||
|
samples/master_details/masterdetailssample.otares
|
||||||
|
@ -29,6 +29,7 @@ interface
|
|||||||
uses
|
uses
|
||||||
MVCFramework.Serializer.Commons,
|
MVCFramework.Serializer.Commons,
|
||||||
MVCFramework.ActiveRecord,
|
MVCFramework.ActiveRecord,
|
||||||
|
MVCFramework.Nullables,
|
||||||
System.Generics.Collections,
|
System.Generics.Collections,
|
||||||
System.Classes;
|
System.Classes;
|
||||||
|
|
||||||
@ -57,7 +58,7 @@ type
|
|||||||
TOrderDetail = class(TMVCActiveRecord)
|
TOrderDetail = class(TMVCActiveRecord)
|
||||||
private
|
private
|
||||||
[MVCTableField('id', [foPrimaryKey, foAutoGenerated])]
|
[MVCTableField('id', [foPrimaryKey, foAutoGenerated])]
|
||||||
fID: Int64;
|
fID: NullableInt64;
|
||||||
[MVCTableField('id_order')]
|
[MVCTableField('id_order')]
|
||||||
fIDOrder: Int64;
|
fIDOrder: Int64;
|
||||||
[MVCTableField('id_article')]
|
[MVCTableField('id_article')]
|
||||||
@ -75,7 +76,7 @@ type
|
|||||||
public
|
public
|
||||||
constructor Create; override;
|
constructor Create; override;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
property ID: Int64 read fID write fID;
|
property ID: NullableInt64 read fID write fID;
|
||||||
property IDOrder: Int64 read fIDOrder write fIDOrder;
|
property IDOrder: Int64 read fIDOrder write fIDOrder;
|
||||||
property IDArticle: Int64 read fIDArticle write fIDArticle;
|
property IDArticle: Int64 read fIDArticle write fIDArticle;
|
||||||
property UnitPrice: Currency read fUnitPrice write fUnitPrice;
|
property UnitPrice: Currency read fUnitPrice write fUnitPrice;
|
||||||
@ -97,9 +98,12 @@ type
|
|||||||
fOrderDate: TDate;
|
fOrderDate: TDate;
|
||||||
[MVCTableField('total')]
|
[MVCTableField('total')]
|
||||||
fTotal: Currency;
|
fTotal: Currency;
|
||||||
|
[MVCOwned]
|
||||||
fDetails: TObjectList<TOrderDetail>;
|
fDetails: TObjectList<TOrderDetail>;
|
||||||
protected
|
protected
|
||||||
procedure OnAfterLoad; override;
|
procedure OnAfterLoad; override;
|
||||||
|
procedure OnAfterUpdate; override;
|
||||||
|
procedure OnAfterInsert; override;
|
||||||
public
|
public
|
||||||
constructor Create; override;
|
constructor Create; override;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
@ -147,12 +151,42 @@ begin
|
|||||||
inherited;
|
inherited;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TOrder.OnAfterInsert;
|
||||||
|
begin
|
||||||
|
inherited;
|
||||||
|
for var lOrderDetail in fDetails do
|
||||||
|
begin
|
||||||
|
lOrderDetail.IDOrder := ID;
|
||||||
|
lOrderDetail.Insert;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TOrder.OnAfterUpdate;
|
||||||
|
begin
|
||||||
|
inherited;
|
||||||
|
var lOrderItems := TMVCActiveRecord.SelectRQL<TOrderDetail>(Format('eq(idorder,%d)', [ID]), 100);
|
||||||
|
try
|
||||||
|
TMVCActiveRecord.Merge<TOrderDetail>(lOrderItems, fDetails)
|
||||||
|
.Apply(
|
||||||
|
procedure (const Obj: TOrderDetail; const EntityAction: TMVCEntityAction;
|
||||||
|
var Handled: Boolean)
|
||||||
|
begin
|
||||||
|
if EntityAction in [eaCreate, eaUpdate] then
|
||||||
|
begin
|
||||||
|
Obj.IDOrder := ID;
|
||||||
|
end;
|
||||||
|
end);
|
||||||
|
finally
|
||||||
|
lOrderItems.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TOrder.OnAfterLoad;
|
procedure TOrder.OnAfterLoad;
|
||||||
var
|
var
|
||||||
lList: TObjectList<TOrderDetail>;
|
lList: TObjectList<TOrderDetail>;
|
||||||
begin
|
begin
|
||||||
inherited;
|
inherited;
|
||||||
lList := TMVCActiveRecord.SelectRQL<TOrderDetail>(Format('eq(order_id,%d)',[ID]), 1000);
|
lList := TMVCActiveRecord.SelectRQL<TOrderDetail>(Format('eq(idOrder,%d)',[ID]), 1000);
|
||||||
try
|
try
|
||||||
fDetails.Clear;
|
fDetails.Clear;
|
||||||
fDetails.AddRange(lList);
|
fDetails.AddRange(lList);
|
||||||
|
@ -67,8 +67,8 @@ uses
|
|||||||
|
|
||||||
procedure TOrdersController.CreateOrder(const [MVCFromBody] Order: TOrder);
|
procedure TOrdersController.CreateOrder(const [MVCFromBody] Order: TOrder);
|
||||||
begin
|
begin
|
||||||
// GetOrdersService.Add(Order);
|
Order.Insert;
|
||||||
// Render201Created('/Orders/' + Order.id.ToString, 'Order Created');
|
Render201Created('/orders/' + Order.id.ToString, 'Order Created');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TOrdersController.CreateOrders(const OrderList: TObjectList<TOrder>);
|
procedure TOrdersController.CreateOrders(const OrderList: TObjectList<TOrder>);
|
||||||
@ -108,13 +108,26 @@ end;
|
|||||||
|
|
||||||
procedure TOrdersController.GetOrders;
|
procedure TOrdersController.GetOrders;
|
||||||
begin
|
begin
|
||||||
// Render(ObjectDict().Add('data', GetOrdersService.GetAll));
|
try
|
||||||
|
Render(ObjectDict().Add('data', TMVCActiveRecord.All<TOrder>));
|
||||||
|
// Render(ObjectDict().Add('data', GetOrdersService.GetByID(id)));
|
||||||
|
except
|
||||||
|
on E: EServiceException do
|
||||||
|
begin
|
||||||
|
raise EMVCException.Create(E.Message, '', 0, 404);
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TOrdersController.GetOrdersByDescription(const Search: String);
|
procedure TOrdersController.GetOrdersByDescription(const Search: String);
|
||||||
var
|
var
|
||||||
lDict: IMVCObjectDictionary;
|
lDict: IMVCObjectDictionary;
|
||||||
begin
|
begin
|
||||||
|
// Render(
|
||||||
|
// ObjectDict()
|
||||||
|
// .Add('data', TMVCActiveRecord.SelectRQL<TOrder>(Format('contains(description,"%s")',[Search]),100))
|
||||||
|
// );
|
||||||
// try
|
// try
|
||||||
// if Search = '' then
|
// if Search = '' then
|
||||||
// begin
|
// begin
|
||||||
@ -137,14 +150,20 @@ end;
|
|||||||
|
|
||||||
procedure TOrdersController.UpdateOrderByID(const Order: TOrder; const id: Integer);
|
procedure TOrdersController.UpdateOrderByID(const Order: TOrder; const id: Integer);
|
||||||
begin
|
begin
|
||||||
// Order.id := id;
|
Order.id := id;
|
||||||
// GetOrdersService.Update(Order);
|
var lCurrentOrder := TMVCActiveRecord.GetByPK<TOrder>(id);
|
||||||
// Render(200, 'Order Updated');
|
try
|
||||||
|
Order.Update();
|
||||||
|
finally
|
||||||
|
lCurrentOrder.Free;
|
||||||
|
end;
|
||||||
|
Render(200, 'Order Updated');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TOrdersController.GetOrderByID(id: Integer);
|
procedure TOrdersController.GetOrderByID(id: Integer);
|
||||||
begin
|
begin
|
||||||
try
|
try
|
||||||
|
Render(TMVCActiveRecord.GetByPK<TOrder>(id));
|
||||||
// Render(ObjectDict().Add('data', GetOrdersService.GetByID(id)));
|
// Render(ObjectDict().Add('data', GetOrdersService.GetByID(id)));
|
||||||
except
|
except
|
||||||
on E: EServiceException do
|
on E: EServiceException do
|
||||||
|
@ -17,7 +17,9 @@ implementation
|
|||||||
uses
|
uses
|
||||||
System.Classes,
|
System.Classes,
|
||||||
System.IOUtils,
|
System.IOUtils,
|
||||||
FireDAC.Comp.Client;
|
FireDAC.Comp.Client,
|
||||||
|
FireDAC.Phys.PG,
|
||||||
|
MVCFramework.SQLGenerators.PostgreSQL;
|
||||||
|
|
||||||
procedure CreateMySQLPrivateConnDef(AIsPooled: boolean);
|
procedure CreateMySQLPrivateConnDef(AIsPooled: boolean);
|
||||||
var
|
var
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
object WebModule1: TWebModule1
|
object WebModule1: TWebModule1
|
||||||
OldCreateOrder = False
|
|
||||||
OnCreate = WebModuleCreate
|
OnCreate = WebModuleCreate
|
||||||
Actions = <
|
Actions = <
|
||||||
item
|
item
|
||||||
@ -9,4 +8,5 @@ object WebModule1: TWebModule1
|
|||||||
end>
|
end>
|
||||||
Height = 230
|
Height = 230
|
||||||
Width = 415
|
Width = 415
|
||||||
|
PixelsPerInch = 96
|
||||||
end
|
end
|
||||||
|
@ -21,7 +21,8 @@ implementation
|
|||||||
{ %CLASSGROUP 'Vcl.Controls.TControl' }
|
{ %CLASSGROUP 'Vcl.Controls.TControl' }
|
||||||
|
|
||||||
uses Controllers.Orders, mvcframework.Middleware.CORS, mvcframework.Middleware.Compression,
|
uses Controllers.Orders, mvcframework.Middleware.CORS, mvcframework.Middleware.Compression,
|
||||||
Controllers.Base, MVCFramework.Commons;
|
Controllers.Base, MVCFramework.Commons, MVCFramework.Middleware.ActiveRecord,
|
||||||
|
FDConnectionConfigU;
|
||||||
|
|
||||||
{$R *.dfm}
|
{$R *.dfm}
|
||||||
|
|
||||||
@ -38,6 +39,7 @@ begin
|
|||||||
{$IFDEF TESTINSTANCE}
|
{$IFDEF TESTINSTANCE}
|
||||||
FEngine.AddController(TPrivateController);
|
FEngine.AddController(TPrivateController);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
FEngine.AddMiddleware(TMVCActiveRecordMiddleware.Create(CON_DEF_NAME, ''));
|
||||||
FEngine.AddMiddleware(TCORSMiddleware.Create);
|
FEngine.AddMiddleware(TCORSMiddleware.Create);
|
||||||
FEngine.AddMiddleware(TMVCCompressionMiddleware.Create(256));
|
FEngine.AddMiddleware(TMVCCompressionMiddleware.Create(256));
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ end;
|
|||||||
begin
|
begin
|
||||||
ReportMemoryLeaksOnShutdown := True;
|
ReportMemoryLeaksOnShutdown := True;
|
||||||
try
|
try
|
||||||
|
CreatePostgresqlPrivateConnDef(True);
|
||||||
if WebRequestHandler <> nil then
|
if WebRequestHandler <> nil then
|
||||||
WebRequestHandler.WebModuleClass := WebModuleClass;
|
WebRequestHandler.WebModuleClass := WebModuleClass;
|
||||||
RunServer(8080);
|
RunServer(8080);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -2748,39 +2748,42 @@ var
|
|||||||
begin
|
begin
|
||||||
lUnitOfWork := TMVCUnitOfWork<T>.Create;
|
lUnitOfWork := TMVCUnitOfWork<T>.Create;
|
||||||
lUnitOfWork.RegisterDelete(CurrentList);
|
lUnitOfWork.RegisterDelete(CurrentList);
|
||||||
lPKType := NewList[i].GetPrimaryKeyFieldType;
|
if NewList.Count > 0 then
|
||||||
for i := 0 to NewList.Count - 1 do
|
|
||||||
begin
|
begin
|
||||||
if NewList[i].PKIsNull then
|
lPKType := NewList[0].GetPrimaryKeyFieldType;
|
||||||
|
for i := 0 to NewList.Count - 1 do
|
||||||
begin
|
begin
|
||||||
lUnitOfWork.RegisterInsert(NewList[i]);
|
if NewList[i].PKIsNull then
|
||||||
continue;
|
begin
|
||||||
end;
|
lUnitOfWork.RegisterInsert(NewList[i]);
|
||||||
|
continue;
|
||||||
|
end;
|
||||||
|
|
||||||
case lPKType of
|
case lPKType of
|
||||||
ftString:
|
ftString:
|
||||||
begin
|
begin
|
||||||
lNeedsToBeUpdated := TMVCUnitOfWork<T>.KeyExistsString(CurrentList,
|
lNeedsToBeUpdated := TMVCUnitOfWork<T>.KeyExistsString(CurrentList,
|
||||||
NewList[i].GetPK.AsString, lFoundAtIndex);
|
NewList[i].GetPK.AsString, lFoundAtIndex);
|
||||||
end;
|
end;
|
||||||
ftInteger:
|
ftInteger:
|
||||||
begin
|
begin
|
||||||
lNeedsToBeUpdated := TMVCUnitOfWork<T>.KeyExistsInt(CurrentList,
|
lNeedsToBeUpdated := TMVCUnitOfWork<T>.KeyExistsInt(CurrentList,
|
||||||
NewList[i].GetPK.AsInteger, lFoundAtIndex);
|
NewList[i].GetPK.AsInteger, lFoundAtIndex);
|
||||||
end;
|
end;
|
||||||
ftLargeInt:
|
ftLargeInt:
|
||||||
begin
|
begin
|
||||||
lNeedsToBeUpdated := TMVCUnitOfWork<T>.KeyExistsInt64(CurrentList,
|
lNeedsToBeUpdated := TMVCUnitOfWork<T>.KeyExistsInt64(CurrentList,
|
||||||
NewList[i].GetPK.AsInt64, lFoundAtIndex);
|
NewList[i].GetPK.AsInt64, lFoundAtIndex);
|
||||||
end;
|
end;
|
||||||
else
|
else
|
||||||
raise EMVCActiveRecord.Create('Invalid primary key type');
|
raise EMVCActiveRecord.Create('Invalid primary key type');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if lNeedsToBeUpdated then
|
if lNeedsToBeUpdated then
|
||||||
lUnitOfWork.RegisterUpdate(NewList[i])
|
lUnitOfWork.RegisterUpdate(NewList[i])
|
||||||
else
|
else
|
||||||
lUnitOfWork.RegisterInsert(NewList[i]);
|
lUnitOfWork.RegisterInsert(NewList[i]);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
Result := lUnitOfWork as IMVCMultiExecutor<T>;
|
Result := lUnitOfWork as IMVCMultiExecutor<T>;
|
||||||
end;
|
end;
|
||||||
@ -3148,7 +3151,7 @@ end;
|
|||||||
|
|
||||||
procedure TMVCUnitOfWork<T>.Apply(const ItemApplyAction: TMVCItemApplyAction<T>);
|
procedure TMVCUnitOfWork<T>.Apply(const ItemApplyAction: TMVCItemApplyAction<T>);
|
||||||
var
|
var
|
||||||
i: UInt32;
|
i: Integer;
|
||||||
lHandled: Boolean;
|
lHandled: Boolean;
|
||||||
begin
|
begin
|
||||||
for i := 0 to fListToInsert.Count - 1 do
|
for i := 0 to fListToInsert.Count - 1 do
|
||||||
@ -3166,7 +3169,7 @@ begin
|
|||||||
DoItemApplyAction(fListToUpdate[i], eaUpdate, ItemApplyAction, lHandled);
|
DoItemApplyAction(fListToUpdate[i], eaUpdate, ItemApplyAction, lHandled);
|
||||||
if not lHandled then
|
if not lHandled then
|
||||||
begin
|
begin
|
||||||
fListToUpdate[i].Update;
|
fListToUpdate[i].Update(True);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
for i := 0 to fListToDelete.Count - 1 do
|
for i := 0 to fListToDelete.Count - 1 do
|
||||||
@ -3175,7 +3178,7 @@ begin
|
|||||||
DoItemApplyAction(fListToDelete[i], eaDelete, ItemApplyAction, lHandled);
|
DoItemApplyAction(fListToDelete[i], eaDelete, ItemApplyAction, lHandled);
|
||||||
if not lHandled then
|
if not lHandled then
|
||||||
begin
|
begin
|
||||||
fListToDelete[i].Delete;
|
fListToDelete[i].Delete(True);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -3246,7 +3249,7 @@ begin
|
|||||||
Result := false;
|
Result := false;
|
||||||
for i := 0 to NewList.Count - 1 do
|
for i := 0 to NewList.Count - 1 do
|
||||||
begin
|
begin
|
||||||
if NewList[i].GetPK.AsInt64 = KeyValue then
|
if (not NewList[i].PKIsNull) and (NewList[i].GetPK.AsInt64 = KeyValue) then
|
||||||
begin
|
begin
|
||||||
Index := i;
|
Index := i;
|
||||||
Exit(True);
|
Exit(True);
|
||||||
|
@ -95,6 +95,12 @@ begin
|
|||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
if fConnectionDefFileName.IsEmpty then
|
||||||
|
begin
|
||||||
|
fConnectionLoaded := True;
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
|
||||||
// if not FDManager.ConnectionDefFileLoaded then
|
// if not FDManager.ConnectionDefFileLoaded then
|
||||||
// begin
|
// begin
|
||||||
FDManager.ConnectionDefFileName := fConnectionDefFileName;
|
FDManager.ConnectionDefFileName := fConnectionDefFileName;
|
||||||
|
@ -39,7 +39,7 @@ type
|
|||||||
fConnection: TFDConnection;
|
fConnection: TFDConnection;
|
||||||
fConDefName: string;
|
fConDefName: string;
|
||||||
procedure CreatePrivateConnDef(AIsPooled: boolean); virtual; abstract;
|
procedure CreatePrivateConnDef(AIsPooled: boolean); virtual; abstract;
|
||||||
procedure LoadData; virtual;
|
procedure LoadData(const JustAFew: Boolean = False); virtual;
|
||||||
procedure AfterDataLoad; virtual; abstract;
|
procedure AfterDataLoad; virtual; abstract;
|
||||||
procedure InternalSetupFixture; virtual;
|
procedure InternalSetupFixture; virtual;
|
||||||
public
|
public
|
||||||
@ -79,6 +79,14 @@ type
|
|||||||
procedure TestMultiThreading;
|
procedure TestMultiThreading;
|
||||||
[Test]
|
[Test]
|
||||||
procedure TestNullables;
|
procedure TestNullables;
|
||||||
|
[Test]
|
||||||
|
procedure TestMergeWhenNewRecords;
|
||||||
|
[Test]
|
||||||
|
procedure TestMergeWhenNewDeletedRecords;
|
||||||
|
[Test]
|
||||||
|
procedure TestMergeWhenChangedRecords;
|
||||||
|
[Test]
|
||||||
|
procedure TestMergeWhenMixedRecords;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
@ -123,7 +131,7 @@ implementation
|
|||||||
uses
|
uses
|
||||||
System.Classes, System.IOUtils, BOs, MVCFramework.ActiveRecord,
|
System.Classes, System.IOUtils, BOs, MVCFramework.ActiveRecord,
|
||||||
System.SysUtils, System.Threading, System.Generics.Collections, Data.DB,
|
System.SysUtils, System.Threading, System.Generics.Collections, Data.DB,
|
||||||
FireDAC.Stan.Intf, ShellAPI, Winapi.Windows;
|
FireDAC.Stan.Intf, ShellAPI, Winapi.Windows, MVCFramework.Logger;
|
||||||
|
|
||||||
const
|
const
|
||||||
_CON_DEF_NAME_SQLITE = 'SQLITECONNECTION';
|
_CON_DEF_NAME_SQLITE = 'SQLITECONNECTION';
|
||||||
@ -215,7 +223,7 @@ begin
|
|||||||
Assert.AreEqual('note1noteupdated', lCustomer.Note);
|
Assert.AreEqual('note1noteupdated', lCustomer.Note);
|
||||||
Assert.AreEqual('bit Time Professionals', lCustomer.CompanyName.Value);
|
Assert.AreEqual('bit Time Professionals', lCustomer.CompanyName.Value);
|
||||||
Assert.AreEqual('Rome, IT', lCustomer.City);
|
Assert.AreEqual('Rome, IT', lCustomer.City);
|
||||||
Assert.AreEqual(1, lCustomer.ID);
|
Assert.AreEqual(1, lCustomer.ID.Value);
|
||||||
Assert.IsFalse(lCustomer.CreationTime.HasValue);
|
Assert.IsFalse(lCustomer.CreationTime.HasValue);
|
||||||
Assert.IsFalse(lCustomer.CreationDate.HasValue);
|
Assert.IsFalse(lCustomer.CreationDate.HasValue);
|
||||||
finally
|
finally
|
||||||
@ -524,6 +532,346 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestActiveRecordBase.TestMergeWhenChangedRecords;
|
||||||
|
var
|
||||||
|
lCustomer: TCustomer;
|
||||||
|
lCustomers: TObjectList<TCustomer>;
|
||||||
|
lCustomersChanges: TObjectList<TCustomer>;
|
||||||
|
lInserted, lUpdated, lDeleted, lTotCustomers : Integer;
|
||||||
|
begin
|
||||||
|
TMVCActiveRecord.DeleteAll(TCustomer);
|
||||||
|
LoadData(true);
|
||||||
|
lCustomers := TMVCActiveRecord.SelectRQL<TCustomer>('eq(rating,1)', 1000);
|
||||||
|
try
|
||||||
|
lCustomersChanges := TObjectList<TCustomer>.Create(True);
|
||||||
|
try
|
||||||
|
for var lCust in lCustomers do
|
||||||
|
begin
|
||||||
|
lCustomer := lCust.Clone;
|
||||||
|
lCustomer.Rating := 10;
|
||||||
|
lCustomersChanges.Add(lCustomer);
|
||||||
|
end;
|
||||||
|
|
||||||
|
//calculate the unit-of-work to merge the lists
|
||||||
|
lInserted := 0;
|
||||||
|
lUpdated := 0;
|
||||||
|
lDeleted := 0;
|
||||||
|
TMVCActiveRecord.Merge<TCustomer>(lCustomers, lCustomersChanges).Apply(
|
||||||
|
procedure (const Customer: TCustomer; const EntityAction: TMVCEntityAction; var Handled: Boolean)
|
||||||
|
begin
|
||||||
|
Handled := False;
|
||||||
|
case EntityAction of
|
||||||
|
eaCreate: begin
|
||||||
|
LogI('Inserting Customer : ' + Customer.ToString);
|
||||||
|
Inc(lInserted);
|
||||||
|
end;
|
||||||
|
eaUpdate: begin
|
||||||
|
LogI('Updating Customer : ' + Customer.ToString);
|
||||||
|
Inc(lUpdated);
|
||||||
|
end;
|
||||||
|
eaDelete: begin
|
||||||
|
LogI('Deleting Customer : ' + Customer.ToString);
|
||||||
|
Inc(lDeleted);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end);
|
||||||
|
finally
|
||||||
|
lCustomersChanges.Free;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
lCustomers.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Assert.AreEqual(0, lInserted);
|
||||||
|
Assert.AreEqual(30, lUpdated);
|
||||||
|
Assert.AreEqual(0, lDeleted);
|
||||||
|
|
||||||
|
lCustomers := TMVCActiveRecord.All<TCustomer>;
|
||||||
|
try
|
||||||
|
Assert.AreEqual(30, lCustomers.Count);
|
||||||
|
finally
|
||||||
|
lCustomers.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
lCustomers := TMVCActiveRecord.SelectRQL<TCustomer>('eq(rating,10)', 1000);
|
||||||
|
try
|
||||||
|
Assert.AreEqual(30, lCustomers.Count);
|
||||||
|
finally
|
||||||
|
lCustomers.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestActiveRecordBase.TestMergeWhenMixedRecords;
|
||||||
|
var
|
||||||
|
lCustomer: TCustomer;
|
||||||
|
lCustomers: TObjectList<TCustomer>;
|
||||||
|
lCustomersChanges: TObjectList<TCustomer>;
|
||||||
|
lInserted, lUpdated, lDeleted, lTotCustomers : Integer;
|
||||||
|
begin
|
||||||
|
TMVCActiveRecord.DeleteAll(TCustomer);
|
||||||
|
LoadData(true);
|
||||||
|
lCustomers := TMVCActiveRecord.SelectRQL<TCustomer>('eq(rating,1)', 1000);
|
||||||
|
try
|
||||||
|
lCustomersChanges := TObjectList<TCustomer>.Create(True);
|
||||||
|
try
|
||||||
|
//these 2 customers will be updated
|
||||||
|
lCustomer := TCustomer.Create;
|
||||||
|
lCustomersChanges.Add(lCustomer);
|
||||||
|
lCustomer.ID := lCustomers[0].ID;
|
||||||
|
lCustomer.Code := 'C8765';
|
||||||
|
lCustomer.CompanyName := '(changed) Company1';
|
||||||
|
lCustomer.City := '(changed) City';
|
||||||
|
lCustomer.Rating := 2;
|
||||||
|
|
||||||
|
lCustomer := TCustomer.Create;
|
||||||
|
lCustomersChanges.Add(lCustomer);
|
||||||
|
lCustomer.ID := lCustomers[1].ID;
|
||||||
|
lCustomer.Code := lCustomers[1].Code;
|
||||||
|
lCustomer.CompanyName := '(changed) Company2';
|
||||||
|
lCustomer.City := '(changed) City';
|
||||||
|
lCustomer.Rating := 2;
|
||||||
|
|
||||||
|
|
||||||
|
//these 2 customer will be created
|
||||||
|
lCustomer := TCustomer.Create;
|
||||||
|
lCustomersChanges.Add(lCustomer);
|
||||||
|
lCustomer.Code := 'C9898';
|
||||||
|
lCustomer.CompanyName := '(new) Company3';
|
||||||
|
lCustomer.City := '(new) New City2';
|
||||||
|
lCustomer.Rating := 3;
|
||||||
|
|
||||||
|
lCustomer := TCustomer.Create;
|
||||||
|
lCustomersChanges.Add(lCustomer);
|
||||||
|
lCustomer.Code := 'C2343';
|
||||||
|
lCustomer.CompanyName := '(new) Company4';
|
||||||
|
lCustomer.City := '(new) New City2';
|
||||||
|
lCustomer.Rating := 3;
|
||||||
|
|
||||||
|
//these 2 customer will remain the same but will be updated
|
||||||
|
lCustomer := TCustomer.Create;
|
||||||
|
lCustomer.Assign(lCustomers[2]);
|
||||||
|
lCustomersChanges.Add(lCustomer);
|
||||||
|
|
||||||
|
lCustomer := TCustomer.Create;
|
||||||
|
lCustomer.Assign(lCustomers[3]);
|
||||||
|
lCustomersChanges.Add(lCustomer);
|
||||||
|
|
||||||
|
//all the other customers will be deleted
|
||||||
|
|
||||||
|
//calculate the unit-of-work to merge the lists
|
||||||
|
lInserted := 0;
|
||||||
|
lUpdated := 0;
|
||||||
|
lDeleted := 0;
|
||||||
|
TMVCActiveRecord.Merge<TCustomer>(lCustomers, lCustomersChanges).Apply(
|
||||||
|
procedure (const Customer: TCustomer; const EntityAction: TMVCEntityAction; var Handled: Boolean)
|
||||||
|
begin
|
||||||
|
Handled := False;
|
||||||
|
case EntityAction of
|
||||||
|
eaCreate: begin
|
||||||
|
LogI('Inserting Customer : ' + Customer.ToString);
|
||||||
|
Inc(lInserted);
|
||||||
|
end;
|
||||||
|
eaUpdate: begin
|
||||||
|
LogI('Updating Customer : ' + Customer.ToString);
|
||||||
|
Inc(lUpdated);
|
||||||
|
end;
|
||||||
|
eaDelete: begin
|
||||||
|
LogI('Deleting Customer : ' + Customer.ToString);
|
||||||
|
Inc(lDeleted);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end);
|
||||||
|
finally
|
||||||
|
lCustomersChanges.Free;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
lCustomers.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Assert.AreEqual(2, lInserted);
|
||||||
|
Assert.AreEqual(4, lUpdated);
|
||||||
|
Assert.AreEqual(26, lDeleted);
|
||||||
|
|
||||||
|
lCustomers := TMVCActiveRecord.All<TCustomer>;
|
||||||
|
try
|
||||||
|
Assert.AreEqual(6, lCustomers.Count);
|
||||||
|
finally
|
||||||
|
lCustomers.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
lCustomers := TMVCActiveRecord.SelectRQL<TCustomer>('eq(rating,3)', 1000);
|
||||||
|
try
|
||||||
|
Assert.AreEqual(2, lCustomers.Count);
|
||||||
|
finally
|
||||||
|
lCustomers.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
lCustomers := TMVCActiveRecord.SelectRQL<TCustomer>('eq(rating,2)', 1000);
|
||||||
|
try
|
||||||
|
Assert.AreEqual(2, lCustomers.Count, 'Customers not updated correctly');
|
||||||
|
finally
|
||||||
|
lCustomers.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
lCustomers := TMVCActiveRecord.SelectRQL<TCustomer>('eq(rating,1)', 1000);
|
||||||
|
try
|
||||||
|
Assert.AreEqual(2, lCustomers.Count);
|
||||||
|
finally
|
||||||
|
lCustomers.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestActiveRecordBase.TestMergeWhenNewDeletedRecords;
|
||||||
|
var
|
||||||
|
lCustomer: TCustomer;
|
||||||
|
lCustomers: TObjectList<TCustomer>;
|
||||||
|
lCustomersChanges: TObjectList<TCustomer>;
|
||||||
|
lInserted, lUpdated, lDeleted, lTotCustomers : Integer;
|
||||||
|
begin
|
||||||
|
TMVCActiveRecord.DeleteAll(TCustomer);
|
||||||
|
LoadData(true);
|
||||||
|
lCustomers := TMVCActiveRecord.SelectRQL<TCustomer>('eq(rating,1)', 1000);
|
||||||
|
try
|
||||||
|
lCustomersChanges := TObjectList<TCustomer>.Create(True);
|
||||||
|
try
|
||||||
|
lTotCustomers := lCustomersChanges.Count;
|
||||||
|
lInserted := 0;
|
||||||
|
lUpdated := 0;
|
||||||
|
lDeleted := 0;
|
||||||
|
//calculate the unit-of-work to merge the lists
|
||||||
|
TMVCActiveRecord.Merge<TCustomer>(lCustomers, lCustomersChanges).Apply(
|
||||||
|
procedure (const Customer: TCustomer; const EntityAction: TMVCEntityAction; var Handled: Boolean)
|
||||||
|
begin
|
||||||
|
Handled := False;
|
||||||
|
case EntityAction of
|
||||||
|
eaCreate: begin
|
||||||
|
LogI('Inserting Customer : ' + Customer.ToString);
|
||||||
|
Inc(lInserted);
|
||||||
|
end;
|
||||||
|
eaUpdate: begin
|
||||||
|
LogI('Updating Customer : ' + Customer.ToString);
|
||||||
|
Inc(lUpdated);
|
||||||
|
end;
|
||||||
|
eaDelete: begin
|
||||||
|
LogI('Deleting Customer : ' + Customer.ToString);
|
||||||
|
Inc(lDeleted);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end);
|
||||||
|
finally
|
||||||
|
lCustomersChanges.Free;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
lCustomers.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Assert.AreEqual(0, lInserted);
|
||||||
|
Assert.AreEqual(0, lUpdated);
|
||||||
|
Assert.AreEqual(30, lDeleted);
|
||||||
|
|
||||||
|
lCustomers := TMVCActiveRecord.All<TCustomer>;
|
||||||
|
try
|
||||||
|
Assert.AreEqual(lTotCustomers, lCustomers.Count);
|
||||||
|
finally
|
||||||
|
lCustomers.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestActiveRecordBase.TestMergeWhenNewRecords;
|
||||||
|
var
|
||||||
|
lCustomer: TCustomer;
|
||||||
|
lCustomers: TObjectList<TCustomer>;
|
||||||
|
lCustomersChanges: TObjectList<TCustomer>;
|
||||||
|
lInserted, lUpdated, lDeleted, lTotCustomers : Integer;
|
||||||
|
begin
|
||||||
|
TMVCActiveRecord.DeleteAll(TCustomer);
|
||||||
|
LoadData(true);
|
||||||
|
lCustomers := TMVCActiveRecord.SelectRQL<TCustomer>('eq(rating,1)', 1000);
|
||||||
|
try
|
||||||
|
lCustomersChanges := TObjectList<TCustomer>.Create(True);
|
||||||
|
try
|
||||||
|
for var lCust in lCustomers do
|
||||||
|
begin
|
||||||
|
lCustomersChanges.Add(lCust.Clone);
|
||||||
|
end;
|
||||||
|
|
||||||
|
//these 2 customer will be created
|
||||||
|
lCustomer := TCustomer.Create;
|
||||||
|
lCustomersChanges.Add(lCustomer);
|
||||||
|
lCustomer.Code := 'C9898';
|
||||||
|
lCustomer.CompanyName := '(new) Company3';
|
||||||
|
lCustomer.City := '(new) New City2';
|
||||||
|
lCustomer.Rating := 3;
|
||||||
|
|
||||||
|
lCustomer := TCustomer.Create;
|
||||||
|
lCustomersChanges.Add(lCustomer);
|
||||||
|
lCustomer.Code := 'C2343';
|
||||||
|
lCustomer.CompanyName := '(new) Company4';
|
||||||
|
lCustomer.City := '(new) New City2';
|
||||||
|
lCustomer.Rating := 3;
|
||||||
|
|
||||||
|
lTotCustomers := lCustomersChanges.Count;
|
||||||
|
|
||||||
|
lInserted := 0;
|
||||||
|
lUpdated := 0;
|
||||||
|
lDeleted := 0;
|
||||||
|
//calculate the unit-of-work to merge the lists
|
||||||
|
TMVCActiveRecord.Merge<TCustomer>(lCustomers, lCustomersChanges).Apply(
|
||||||
|
procedure (const Customer: TCustomer; const EntityAction: TMVCEntityAction; var Handled: Boolean)
|
||||||
|
begin
|
||||||
|
Handled := False;
|
||||||
|
case EntityAction of
|
||||||
|
eaCreate: begin
|
||||||
|
LogI('Inserting Customer : ' + Customer.ToString);
|
||||||
|
Inc(lInserted);
|
||||||
|
end;
|
||||||
|
eaUpdate: begin
|
||||||
|
LogI('Updating Customer : ' + Customer.ToString);
|
||||||
|
Inc(lUpdated);
|
||||||
|
end;
|
||||||
|
eaDelete: begin
|
||||||
|
LogI('Deleting Customer : ' + Customer.ToString);
|
||||||
|
Inc(lDeleted);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end);
|
||||||
|
finally
|
||||||
|
lCustomersChanges.Free;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
lCustomers.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Assert.AreEqual(2, lInserted);
|
||||||
|
Assert.AreEqual(30, lUpdated);
|
||||||
|
Assert.AreEqual(0, lDeleted);
|
||||||
|
|
||||||
|
lCustomers := TMVCActiveRecord.All<TCustomer>;
|
||||||
|
try
|
||||||
|
Assert.AreEqual(lTotCustomers, lCustomers.Count);
|
||||||
|
finally
|
||||||
|
lCustomers.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
lCustomers := TMVCActiveRecord.SelectRQL<TCustomer>('eq(rating,1)', 1000);
|
||||||
|
try
|
||||||
|
Assert.AreEqual(lTotCustomers - 2, lCustomers.Count, 'Some customer changed when should not change');
|
||||||
|
finally
|
||||||
|
lCustomers.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
lCustomers := TMVCActiveRecord.SelectRQL<TCustomer>('eq(rating,3)', 1000);
|
||||||
|
try
|
||||||
|
Assert.AreEqual(2, lCustomers.Count, 'Some customer changed when should not change');
|
||||||
|
finally
|
||||||
|
lCustomers.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TTestActiveRecordBase.TestMultiThreading;
|
procedure TTestActiveRecordBase.TestMultiThreading;
|
||||||
begin
|
begin
|
||||||
LoadData;
|
LoadData;
|
||||||
@ -870,7 +1218,7 @@ begin
|
|||||||
// do nothing
|
// do nothing
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TTestActiveRecordBase.LoadData;
|
procedure TTestActiveRecordBase.LoadData(const JustAFew: Boolean);
|
||||||
var
|
var
|
||||||
lTasks: TArray<ITask>;
|
lTasks: TArray<ITask>;
|
||||||
lProc: TProc;
|
lProc: TProc;
|
||||||
@ -886,8 +1234,10 @@ begin
|
|||||||
lCustomer: TCustomer;
|
lCustomer: TCustomer;
|
||||||
I: Integer;
|
I: Integer;
|
||||||
begin
|
begin
|
||||||
ActiveRecordConnectionsRegistry.AddDefaultConnection(TFDConnection.Create(nil), True);
|
//ActiveRecordConnectionsRegistry.AddDefaultConnection(TFDConnection.Create(nil), True);
|
||||||
|
ActiveRecordConnectionsRegistry.AddConnection('load', TFDConnection.Create(nil), True);
|
||||||
try
|
try
|
||||||
|
ActiveRecordConnectionsRegistry.SetCurrent('load');
|
||||||
ActiveRecordConnectionsRegistry.GetCurrent.ConnectionDefName := fConDefName;
|
ActiveRecordConnectionsRegistry.GetCurrent.ConnectionDefName := fConDefName;
|
||||||
for I := 1 to 30 do
|
for I := 1 to 30 do
|
||||||
begin
|
begin
|
||||||
@ -899,6 +1249,7 @@ begin
|
|||||||
Format('%s %s %s', [lCustomer.City, Stuff[Random(high(Stuff) + 1)],
|
Format('%s %s %s', [lCustomer.City, Stuff[Random(high(Stuff) + 1)],
|
||||||
CompanySuffix[Random(high(CompanySuffix) + 1)]]);
|
CompanySuffix[Random(high(CompanySuffix) + 1)]]);
|
||||||
lCustomer.Note := Stuff[I mod Length(Stuff)];
|
lCustomer.Note := Stuff[I mod Length(Stuff)];
|
||||||
|
lCustomer.Rating := 1;
|
||||||
lCustomer.CreationTime := EncodeTime(I mod 23, I, 60 - 1, 0);
|
lCustomer.CreationTime := EncodeTime(I mod 23, I, 60 - 1, 0);
|
||||||
lCustomer.CreationDate := EncodeDate(2020 - I, (I mod 12) + 1, (I mod 27) + 1);
|
lCustomer.CreationDate := EncodeDate(2020 - I, (I mod 12) + 1, (I mod 27) + 1);
|
||||||
lCustomer.Insert;
|
lCustomer.Insert;
|
||||||
@ -907,26 +1258,36 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
finally
|
finally
|
||||||
ActiveRecordConnectionsRegistry.RemoveDefaultConnection;
|
ActiveRecordConnectionsRegistry.RemoveConnection('load');
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
AfterDataLoad;
|
AfterDataLoad;
|
||||||
|
|
||||||
lTasks := [TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc),
|
if JustAFew then
|
||||||
TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc),
|
begin
|
||||||
TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc),
|
lProc();
|
||||||
TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc),
|
ActiveRecordConnectionsRegistry.SetCurrent('default');
|
||||||
TTask.Run(lProc)];
|
end
|
||||||
TTask.WaitForAll(lTasks);
|
else
|
||||||
|
begin
|
||||||
|
lTasks := [TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc),
|
||||||
|
TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc),
|
||||||
|
TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc),
|
||||||
|
TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc), TTask.Run(lProc),
|
||||||
|
TTask.Run(lProc)];
|
||||||
|
TTask.WaitForAll(lTasks);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TTestActiveRecordBase.SetupFixturePG;
|
procedure TTestActiveRecordBase.SetupFixturePG;
|
||||||
begin
|
begin
|
||||||
|
LogI('** Setup Fixture: ' + ClassName);
|
||||||
InternalSetupFixture;
|
InternalSetupFixture;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TTestActiveRecordSQLite.Setup;
|
procedure TTestActiveRecordSQLite.Setup;
|
||||||
begin
|
begin
|
||||||
|
LogI('** Setup Test: ' + ClassName);
|
||||||
fConDefName := _CON_DEF_NAME_SQLITE;
|
fConDefName := _CON_DEF_NAME_SQLITE;
|
||||||
fConnection := TFDConnection.Create(nil);
|
fConnection := TFDConnection.Create(nil);
|
||||||
fConnection.ConnectionDefName := fConDefName;
|
fConnection.ConnectionDefName := fConDefName;
|
||||||
@ -1009,6 +1370,7 @@ end;
|
|||||||
|
|
||||||
procedure TTestActiveRecordFirebird.Setup;
|
procedure TTestActiveRecordFirebird.Setup;
|
||||||
begin
|
begin
|
||||||
|
LogI('** Setup Test: ' + ClassName);
|
||||||
fConDefName := _CON_DEF_NAME_FIREBIRD;
|
fConDefName := _CON_DEF_NAME_FIREBIRD;
|
||||||
fConnection := TFDConnection.Create(nil);
|
fConnection := TFDConnection.Create(nil);
|
||||||
fConnection.ConnectionDefName := fConDefName;
|
fConnection.ConnectionDefName := fConDefName;
|
||||||
@ -1116,6 +1478,7 @@ procedure TTestActiveRecordPostgreSQL.Setup;
|
|||||||
var
|
var
|
||||||
lInitDBStructure: boolean;
|
lInitDBStructure: boolean;
|
||||||
begin
|
begin
|
||||||
|
LogI('** Setup Test: ' + ClassName);
|
||||||
lInitDBStructure := false;
|
lInitDBStructure := false;
|
||||||
|
|
||||||
if not GPGIsInitialized then
|
if not GPGIsInitialized then
|
||||||
|
@ -27,12 +27,12 @@ unit BOs;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
system.TimeSpan, system.SysUtils, generics.collections, system.Classes,
|
system.TimeSpan, generics.collections, system.Classes,
|
||||||
system.Rtti, MVCFramework.Serializer.Commons, JsonDataObjects,
|
system.Rtti, MVCFramework.Serializer.Commons, JsonDataObjects,
|
||||||
MVCFramework.ActiveRecord, MVCFramework.Nullables,
|
MVCFramework.ActiveRecord, MVCFramework.Nullables,
|
||||||
MVCFramework.SQLGenerators.SQLite, MVCFramework.SQLGenerators.Firebird,
|
MVCFramework.SQLGenerators.SQLite, MVCFramework.SQLGenerators.Firebird,
|
||||||
MVCFramework.SQLGenerators.PostgreSQL,
|
MVCFramework.SQLGenerators.PostgreSQL,
|
||||||
FireDAC.Stan.Param, Data.DB;
|
FireDAC.Stan.Param, Data.DB, System.SysUtils;
|
||||||
|
|
||||||
const
|
const
|
||||||
SQLs_SQLITE: array [0 .. 4] of string =
|
SQLs_SQLITE: array [0 .. 4] of string =
|
||||||
@ -98,7 +98,7 @@ type
|
|||||||
TCustomer = class(TMVCActiveRecord)
|
TCustomer = class(TMVCActiveRecord)
|
||||||
private
|
private
|
||||||
[MVCTableField('id', [foPrimaryKey, foAutoGenerated])]
|
[MVCTableField('id', [foPrimaryKey, foAutoGenerated])]
|
||||||
fID: Integer;
|
fID: NullableInt32;
|
||||||
[MVCTableField('code')]
|
[MVCTableField('code')]
|
||||||
fCode: NullableString;
|
fCode: NullableString;
|
||||||
[MVCTableField('description')]
|
[MVCTableField('description')]
|
||||||
@ -114,7 +114,10 @@ type
|
|||||||
[MVCTableField('creation_date')]
|
[MVCTableField('creation_date')]
|
||||||
fCreationDate: NullableTDate;
|
fCreationDate: NullableTDate;
|
||||||
public
|
public
|
||||||
property ID: Integer read fID write fID;
|
procedure Assign(Customer: TCustomer); overload;
|
||||||
|
function Clone: TCustomer;
|
||||||
|
function ToString: String; override;
|
||||||
|
property ID: NullableInt32 read fID write fID;
|
||||||
property Code: NullableString read fCode write fCode;
|
property Code: NullableString read fCode write fCode;
|
||||||
property CompanyName: NullableString read fCompanyName write fCompanyName;
|
property CompanyName: NullableString read fCompanyName write fCompanyName;
|
||||||
property City: string read fCity write fCity;
|
property City: string read fCity write fCity;
|
||||||
@ -1281,4 +1284,29 @@ begin
|
|||||||
FMyDateTime := Value;
|
FMyDateTime := Value;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TCustomer }
|
||||||
|
|
||||||
|
procedure TCustomer.Assign(Customer: TCustomer);
|
||||||
|
begin
|
||||||
|
Self.fID := Customer.fID;
|
||||||
|
Self.fCode := Customer.fCode;
|
||||||
|
Self.fCompanyName := Customer.fCompanyName;
|
||||||
|
Self.fCity := Customer.fCity;
|
||||||
|
Self.fRating := Customer.fRating;
|
||||||
|
Self.fNote := Customer.fNote;
|
||||||
|
Self.fCreationTime := Customer.fCreationTime;
|
||||||
|
Self.fCreationDate := Customer.fCreationDate;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TCustomer.Clone: TCustomer;
|
||||||
|
begin
|
||||||
|
Result := TCustomer.Create;
|
||||||
|
Result.Assign(Self);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TCustomer.ToString: String;
|
||||||
|
begin
|
||||||
|
Result := inherited + Format(' [ID:%5d][Company: %s]', [ID.ValueOrDefault, CompanyName.ValueOrDefault]);
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<ProjectVersion>19.3</ProjectVersion>
|
<ProjectVersion>19.3</ProjectVersion>
|
||||||
<FrameworkType>VCL</FrameworkType>
|
<FrameworkType>VCL</FrameworkType>
|
||||||
<Base>True</Base>
|
<Base>True</Base>
|
||||||
<Config Condition="'$(Config)'==''">CONSOLE</Config>
|
<Config Condition="'$(Config)'==''">Debug</Config>
|
||||||
<Platform Condition="'$(Platform)'==''">Win32</Platform>
|
<Platform Condition="'$(Platform)'==''">Win32</Platform>
|
||||||
<TargetedPlatforms>1</TargetedPlatforms>
|
<TargetedPlatforms>1</TargetedPlatforms>
|
||||||
<AppType>Console</AppType>
|
<AppType>Console</AppType>
|
||||||
@ -107,6 +107,7 @@
|
|||||||
<DCC_S>false</DCC_S>
|
<DCC_S>false</DCC_S>
|
||||||
<DCC_F>false</DCC_F>
|
<DCC_F>false</DCC_F>
|
||||||
<DCC_K>false</DCC_K>
|
<DCC_K>false</DCC_K>
|
||||||
|
<DCC_Define>TESTINSIGHT;DEBUG;$(DCC_Define)</DCC_Define>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Base_Win32)'!=''">
|
<PropertyGroup Condition="'$(Base_Win32)'!=''">
|
||||||
<DCC_ShowGeneralMessages>true</DCC_ShowGeneralMessages>
|
<DCC_ShowGeneralMessages>true</DCC_ShowGeneralMessages>
|
||||||
@ -303,12 +304,14 @@
|
|||||||
<Source Name="MainSource">DMVCFrameworkTests.dpr</Source>
|
<Source Name="MainSource">DMVCFrameworkTests.dpr</Source>
|
||||||
</Source>
|
</Source>
|
||||||
<Excluded_Packages>
|
<Excluded_Packages>
|
||||||
<Excluded_Packages Name="$(BDSBIN)\dcloffice2k270.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
|
<Excluded_Packages Name="$(BDSBIN)\bcboffice2k280.bpl">Embarcadero C++Builder Office 2000 Servers Package</Excluded_Packages>
|
||||||
<Excluded_Packages Name="$(BDSBIN)\dclofficexp270.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages>
|
<Excluded_Packages Name="$(BDSBIN)\bcbofficexp280.bpl">Embarcadero C++Builder Office XP Servers Package</Excluded_Packages>
|
||||||
|
<Excluded_Packages Name="$(BDSBIN)\dcloffice2k280.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
|
||||||
|
<Excluded_Packages Name="$(BDSBIN)\dclofficexp280.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages>
|
||||||
</Excluded_Packages>
|
</Excluded_Packages>
|
||||||
</Delphi.Personality>
|
</Delphi.Personality>
|
||||||
<Deployment Version="3">
|
<Deployment Version="3">
|
||||||
<DeployFile LocalName="Win32\Debug\DMVCFrameworkTests.exe" Configuration="Debug" Class="ProjectOutput">
|
<DeployFile LocalName="bin\DMVCFrameworkTests.exe" Configuration="TESTINSIGHT" Class="ProjectOutput">
|
||||||
<Platform Name="Win32">
|
<Platform Name="Win32">
|
||||||
<RemoteName>DMVCFrameworkTests.exe</RemoteName>
|
<RemoteName>DMVCFrameworkTests.exe</RemoteName>
|
||||||
<Overwrite>true</Overwrite>
|
<Overwrite>true</Overwrite>
|
||||||
@ -332,13 +335,13 @@
|
|||||||
<Overwrite>true</Overwrite>
|
<Overwrite>true</Overwrite>
|
||||||
</Platform>
|
</Platform>
|
||||||
</DeployFile>
|
</DeployFile>
|
||||||
<DeployFile LocalName="$(BDS)\Redist\osx32\libcgunwind.1.0.dylib" Class="DependencyModule">
|
<DeployFile LocalName="$(BDS)\Redist\iossim32\libcgunwind.1.0.dylib" Class="DependencyModule">
|
||||||
<Platform Name="OSX32">
|
<Platform Name="iOSSimulator">
|
||||||
<Overwrite>true</Overwrite>
|
<Overwrite>true</Overwrite>
|
||||||
</Platform>
|
</Platform>
|
||||||
</DeployFile>
|
</DeployFile>
|
||||||
<DeployFile LocalName="$(BDS)\Redist\iossim32\libcgunwind.1.0.dylib" Class="DependencyModule">
|
<DeployFile LocalName="$(BDS)\Redist\osx32\libcgunwind.1.0.dylib" Class="DependencyModule">
|
||||||
<Platform Name="iOSSimulator">
|
<Platform Name="OSX32">
|
||||||
<Overwrite>true</Overwrite>
|
<Overwrite>true</Overwrite>
|
||||||
</Platform>
|
</Platform>
|
||||||
</DeployFile>
|
</DeployFile>
|
||||||
@ -360,7 +363,7 @@
|
|||||||
<Overwrite>true</Overwrite>
|
<Overwrite>true</Overwrite>
|
||||||
</Platform>
|
</Platform>
|
||||||
</DeployFile>
|
</DeployFile>
|
||||||
<DeployFile LocalName="bin\DMVCFrameworkTests.exe" Configuration="TESTINSIGHT" Class="ProjectOutput">
|
<DeployFile LocalName="Win32\Debug\DMVCFrameworkTests.exe" Configuration="Debug" Class="ProjectOutput">
|
||||||
<Platform Name="Win32">
|
<Platform Name="Win32">
|
||||||
<RemoteName>DMVCFrameworkTests.exe</RemoteName>
|
<RemoteName>DMVCFrameworkTests.exe</RemoteName>
|
||||||
<Overwrite>true</Overwrite>
|
<Overwrite>true</Overwrite>
|
||||||
|
Loading…
Reference in New Issue
Block a user