Insert record on M/D with datasetfield

Hi, I rewrite my old problem because my old messages were lost due my mail modification.

I have the problem to insert new records on Master and Detail table on my WPA application
with settings follow showed. If you need i can resend you my sample by mail.

Can you help me ?

Thx

--------------------------------- TABLES ON DB ----------------------------------

CREATE TABLE MASTER_TABLE (
ID_MAS INTEGER NOT NULL PRIMARY KEY, <-- NOTE AUTOINCREMENT ------
DESCRIPTION VARCHAR(50),
DATE_COLL DATETIME2,
IN_COLL BIT NOT NULL DEFAULT (1),
INFO_CLI TEXT,
TEMPER NUMERIC(10,2)
);

CREATE TABLE DET_1_TABLE (
ID_MAS INTEGER NOT NULL,
ID_DET1 INTEGER NOT NULL,
DESCRIPTION VARCHAR(50),
DATE_COLL DATETIME2,
IN_COLL BIT NOT NULL DEFAULT (1),
INFO_CLI TEXT,
TEMPER NUMERIC(10,2),

PRIMARY KEY (ID_MAS, ID_DET1),

CONSTRAINT FK_DET1TABLE FOREIGN KEY (ID_MAS) REFERENCES MASTER_TABLE(ID_MAS) ON DELETE CASCADE
);

---------------------------------- ENTITY SETTINGS SERVER SIDE ------------------------------------

type
TDET_1_TABLE = class;
TDET_2_TABLE = class;
TMASTER_TABLE = class;

[Entity]
[Table('MASTER_TABLE')]
[Id('FID_MAS', TIdGenerator.IdentityOrSequence)]
TMASTER_TABLE = class
private
[Column('ID_MAS', [TColumnProp.Required, TColumnProp.NoInsert, TColumnProp.NoUpdate])]
FID_MAS: Integer;

[Column('DESCRIPTION', [], 50)]
FDESCRIPTION: Nullable<string>;
[Column('DATE_COLL', [])]
FDATE_COLL: Nullable<string>;
[Column('IN_COLL', [TColumnProp.Required])]
FIN_COLL: Boolean;
[Column('INFO_CLI', [], 50)]
FINFO_CLI: Nullable<string>;
[Column('TEMPER', [], 10, 2)]
FTEMPER: Nullable<Double>;

[ManyValuedAssociation([TAssociationProp.Lazy], CascadeTypeAllRemoveOrphan)]
[ForeignJoinColumn('ID_MAS', [TColumnProp.Required])]
FDET_1_TABLE: Proxy<TList<TDET_1_TABLE>>;

Function Get_DET_1_TABLE: TList<TDET_1_TABLE>;

public
constructor Create; overload;
destructor Destroy; override;

property ID_MAS: Integer read FID_MAS write FID_MAS;
property DESCRIPTION: Nullable<string> read FDESCRIPTION write FDESCRIPTION;
property DATE_COLL: Nullable<string> read FDATE_COLL write FDATE_COLL;
property IN_COLL: Boolean read FIN_COLL write FIN_COLL;
property INFO_CLI: Nullable<string> read FINFO_CLI write FINFO_CLI;
property TEMPER: Nullable<Double> read FTEMPER write FTEMPER;

end;

[Entity]
[Table('DET_1_TABLE')]
[Id('FID_MAS', TIdGenerator.None)]
[Id('FID_DET1', TIdGenerator.None)]
TDET_1_TABLE = class
private
[Column('ID_MAS', [TColumnProp.Required])]
FID_MAS: Integer;
[Column('ID_DET1', [TColumnProp.Required])]
FID_DET1: Integer;
[Column('DESCRIPTION', [], 50)]
FDESCRIPTION: Nullable;
[Column('DATE_COLL', [])]
FDATE_COLL: Nullable;
[Column('IN_COLL', [TColumnProp.Required])]
FIN_COLL: Boolean;
[Column('INFO_CLI', [], 50)]
FINFO_CLI: Nullable;
[Column('TEMPER', [], 10, 2)]
FTEMPER: Nullable;
public
property ID_MAS: Integer read FID_MAS write FID_MAS;
property ID_DET1: Integer read FID_DET1 write FID_DET1;
property DESCRIPTION: Nullable read FDESCRIPTION write FDESCRIPTION;
property DATE_COLL: Nullable read FDATE_COLL write FDATE_COLL;
property IN_COLL: Boolean read FIN_COLL write FIN_COLL;
property INFO_CLI: Nullable read FINFO_CLI write FINFO_CLI;
property TEMPER: Nullable read FTEMPER write FTEMPER;
end;

implementation

constructor TMASTER_TABLE.Create;
begin
FDET_1_TABLE.SetInitialValue(TList<TDET_1_TABLE>.Create);
end;

function TMASTER_TABLE.Get_DET_1_TABLE: TList<TDET_1_TABLE>;
begin
Result := FDET_1_TABLE.Value;
end;

destructor TMASTER_TABLE.Destroy;
begin
FDET_1_TABLE.DestroyValue;
inherited;
end;

---------------------------------- WPA (CLIENT SIDE) SETTINGS ------------------------------

wdMaster and wdDetail : TXDataWebDataSet;

with wdMaster.QueryString := $expand=DET_1_TABLE

procedure wdMasterAfterScroll(DataSet: TDataSet);
begin
wdDetail.Close();
wdDetail.SetJsonData(wdMasterMDET_1_TABLE.Value);
wdDetail.Open();
end;

procedure TfrmMain.btSaveAllClick(Sender: TObject);
begin
If wdMaster.State In [dsEdit, dsInsert] Then
wdMaster.Post();
If wdDetail.State In [dsEdit, dsInsert] Then
wdDetail.Post();

wdMaster.ApplyUpdates();
wdD1.ApplyUpdates();
end;

any news for me ?

We need to allocate time to investigate this.

You can set the "master" record by using the @xdata.ref notation. This is what you could use:

procedure TfrmMain.wdD1NewRecord(DataSet: TDataSet);
begin
  TJSObject(wdD1.CurrentData)['ID_MAS@xdata.ref'] :=
    Format('MASTER_TABLE(%d)', [TJSObject(wdM.CurrentData)['ID_MAS']]);
  wdD1.FieldByName('ID_Det1').AsInteger := 22;
  wdD1.FieldByName('DET_2_TABLE').Value := TJSArray.new;
end;

Also, if you have a detail referencing the master, you should not have this:

  [Entity]
  [Table('DET_1_TABLE')]
  [Id('FID_MAS', TIdGenerator.None)]
  [Id('FID_DET1', TIdGenerator.None)]
  TDET_1_TABLE = class
  private
    [Column('ID_MAS', [TColumnProp.Required])]
    FID_MAS: Integer;

    [Column('ID_DET1', [TColumnProp.Required])]
    FID_DET1: Integer;

but instead, you should have this:

  [Entity]
  [Table('DET_1_TABLE')]
  [Id('FID_MAS', TIdGenerator.None)]
  [Id('FID_DET1', TIdGenerator.None)]
  TDET_1_TABLE = class
  private
    [Association([TAssociationProp.Lazy], CascadeTypeAllButRemove)]
    [JoinColumn('ID_MAS', [TColumnProp.Required])]
    FID_MAS: TMASTER_TABLE

    [Column('ID_DET1', [TColumnProp.Required])]
    FID_DET1: Integer;

and then in master table you must join the two sides of association:

    [ManyValuedAssociation([TAssociationProp.Lazy], CascadeTypeAllRemoveOrphan, ‘FID_MAS')]
    FDET_1_TABLE: Proxy<TList<TDET_1_TABLE>>;

Hi wagner, thank you very much for help, now go better : i can insert records in detail table but not in master table. How can do it ? Thx

Solved !! with

procedure TfrmMain.wdMNewRecord(DataSet: TDataSet);
begin
DataSet.FieldByName('DET_1_TABLE').Value := TJSArray.new;
end;

Thank you

1 Like

Hi wagner

When i have a ID_MAS you show me to use :

TJSObject(wdD1.CurrentData)['ID_MAS@xdata.ref'] :=
Format('MASTER_TABLE(%d)', [TJSObject(wdM.CurrentData)['ID_MAS']]);

But when master is a new record with ID_MAS not assigned what can i assign on detail table ?

Thx

The test project you sent us saves the detail immediately. If you want to keep it that way, your UI then must be sure master is saved before saving the children.

Hi in the test i sent you i can't delete detail records .
if i do : wdD1.Delete; wdD1.ApplyUpdates();
record is not deleted from DB ! there is any settings in entity structure on the server side ?

thx

Hi wagner i sent you a mail with my sample test updated. Bye

Hi, any news for me ? i'm freezed :(

EntityTest.zip (1.8 MB)

Hi wagner

Attached an updated my sample test (file is .rar) with your suggested modifications. Now I have a problem to delete or modify detail records : if I do this I have a error attached. There is a entity structure problem ?

Another simple thing : how can I known if there are updates to apply in TXDataWebDataSet ? if I use

If wdD1.Modified Then
wdD1.ApplyUpdates();

Go fine ?

I hope in your help ! BYE

Hi i now i updated my TMSWebCoreSetupWrapper to last version and i have another error :slight_smile:

Now i'm very desperate !!!

Sorry for the delay. We had to adjust several items. Here is the updated project that performs the CRUD operations. We modified the approach to use a normal object for the ID_MAS reference.

SampleGuidoCavalera.zip (89.9 KB)

Hi on the detail table now i have a Identity field (auto inc) and i changed
[Id('FID_DET1', TIdGenerator.None)] to [Id('FID_DET1', TIdGenerator.IdentityOrSequence)] BUT when i insert a record now (in client) i have an error : Cannot insert explicit value for identity column in table 'DET_1_TABLE' when IDENTITY_INSERT is set to OFF.

How can solve it ?

This is a limitation of the database. If you have turned on Identity generator, why are you manually providing an id value in the field? Either keep it None and set the value yourself, or make it Identity and do not set a value in the id field.

Sorry for the incomplete information, but really i use MS SQL server where i have on detail table the PK like this :
COD_ART INTEGER NOT NULL,
ID_RIGO INTEGER IDENTITY(1,1),

Yes, what I said remains true.

ok but i keep it an idenity and i not set a value to it BUT i ve this error when record is applied. i must change something to an entities structure ?