Page 1 of 1

LocalMasterDetail did not work Correctly!!

Posted: Thu 29 Jul 2010 19:00
by ahijazi
Dear DevArt;
After upgrade to ODAC 6.90.0.59 edition, a new issue raised in my applications, where I use LocalMasterDetail option I found the following:
1- Insert an new record in the Master table, without post;
2- Insert record in the Detail table, the record is inserted, but after post the detail record it become hidden ???
3- Post the mater record it will become visible again ????!!!

below a sample that demonstrate the issue, note that in ODAC 6.50.0.34 the issue are not exists ??!!!!!
Thanks in Advanced
Ahmed Hijazi P.Eng.

Code: Select all

var
  snConnection      : TOraSession;
  tblDepts, tblEmps : TOraTable;
  dsDepts           : TOraDataSource;

begin
  snConnection  := TOraSession.Create(self);
  tblDepts      := TOraTable.Create(self);
  tblEmps       := TOraTable.Create(self);
  dsDepts       := TOraDataSource.Create(self);



  with snConnection do begin
    Options.Direct := True;
    Username       := 'dblock';
    Password       := 'dblock';
    Server         := 'gisserver::gisdb';
    AutoCommit     := False;
    Connect;
    try
      ExecSQL('drop table Emps', []);
      ExecSQL('drop table Depts', []);
    except
    end;

    ExecSQL('create table DEPTS(OID NUMBER(8) not null, NAME VARCHAR2(50) not null, constraint TBLMASTER_PK primary key (OID))', []);
    ExecSQL('create table EMPS(OID NUMBER(8) not null, NAME VARCHAR2(50),DEPT_OID  NUMBER(8),constraint EMPS_PK primary key (OID), constraint EMPS_FK foreign key (DEPT_OID) references DEPTS (OID))', []);
  end;

  with tblDepts do begin
    TableName     := 'DEPTS';
    KeyFields     := 'OID';
    Session       := snConnection;
    CachedUpdates := True;
  end;

  dsDepts.DataSet := tblDepts;

  with tblEmps do begin
    TableName     := 'EMPS';
    MasterFields  := 'OID';
    DetailFields  := 'DEPT_OID';
    MasterSource  := dsDepts;
    KeyFields     := 'OID';
    Session       := snConnection;
    CachedUpdates := True;
    Options.LocalMasterDetail := True;
  end;


  tblDepts.open;
  tblEmps.Open;


  tblDepts.Insert;
  tblDepts.FieldByName('OID').Value  := 1;
  tblDepts.FieldByName('Name').Value := 'Dept A';

  // Note that I have not Post, in my case i need the Detail recod to be inserted first then Post the Master Record.

  with tblEmps do begin
    Append;
    FieldByName('OID').Value       := 1;
    FieldByName('Name').Value      := 'Emp A';
    FieldByName('Dept_OID').Value  := 1;
    Post;

    Append;
    FieldByName('OID').Value       := 2;
    FieldByName('Name').Value      := 'Emp B';
    FieldByName('Dept_OID').Value  := 1;
    Post;


    // Values will not appears ??, in the ODAC 6.50.0.34, it work fine, but in ODAC6.90.0.57 it's not !!!!!
    First;
    ShowMessage(FieldByName('Name').AsString); // Empty string displayed
    Next;
    ShowMessage(FieldByName('Name').AsString); // Empty string displayed


    // But after I execute the post of the master table is shown normaly !!!!! 
    tblDepts.Post;

    First;
    ShowMessage(FieldByName('Name').AsString); // "Emp A" displayed
    Next;
    ShowMessage(FieldByName('Name').AsString); // "Emp B" displayed
  end;

Posted: Mon 02 Aug 2010 15:44
by bork
Hello

Thank you for the information. We have reproduced your issue. We will notify you as soon as we have any result.

Posted: Thu 05 Aug 2010 14:52
by bork
Hello

You can use the RefreshParamsOnInsert variable to return old behavior. If you set the RefreshParamsOnInsert variable to True, then detail dataset will be refreshed before you post a new record. New behavior was added for improving performance and avoiding refreshing detail dataset on each master dataset field changing.

Now detail dataset is not refreshed if master dataset doesn't have any records. This is fixed and this fix will be included in the next ODAC build.

Posted: Thu 05 Aug 2010 17:55
by ahijazi
Dear Devart;

Can I make any workaround unitl your NextBuild ???

//
I modify the TCustomDADataSet.LocalDetailFilter little bit to fix this issue
as flow

Code: Select all

function TCustomDADataSet.LocalDetailFilter(RecBuf: IntPtr): boolean;
var
  DataSet: TDataSet;
  i: Integer;
begin
  Result := True;

  if FDataLink.DataSource  nil then begin
    DataSet := FDataLink.DataSource.DataSet;
    if (DataSet  nil) and DataSet.Active then begin
      // aHijazi: just add   --     or (DataSet.State in [dsInsert]) -- 
      Result :=  (DataSet.RecordCount  0) or (DataSet.State in [dsInsert]);
      if not Result then Exit;
    end;
  end;

  for i := 0 to Length(FLocalMDLinks) - 1 do
    with FLocalMDLinks[i] do begin
      if not Result then
        Break;
      if IsNull or TMemData(Data).GetNull(FieldNo, RecBuf) then
        Result := IsNull and TMemData(Data).GetNull(FieldNo, RecBuf)
      else
        Result := TMemData(Data).CompareFieldValue(Buffer, BufferType, Data.Fields[FieldNo - 1], RecBuf, []) = 0;
    end;
can I use this modified code till you release the Next Build

Posted: Fri 06 Aug 2010 09:39
by bork
Hello

If you have ODAC with source code, then you can modify the TCustomDADataSet.LocalDetailFilter method:

Code: Select all

function TCustomDADataSet.LocalDetailFilter(RecBuf: IntPtr): boolean;
var
  DataSet: TDataSet;
  i: Integer;
begin
  Result := True;

  if FDataLink.DataSource  nil then begin
    DataSet := FDataLink.DataSource.DataSet;
    if (DataSet  nil) and DataSet.Active then begin
      // RefreshParamsOnInsert - returns old behavior
      Result := RefreshParamsOnInsert or (DataSet.RecordCount  0);
      if not Result then
        Exit;
    end;
  end;

  for i := 0 to Length(FLocalMDLinks) - 1 do
    with FLocalMDLinks[i] do begin
      if not Result then
        Break;
      if IsNull or TMemData(Data).GetNull(FieldNo, RecBuf) then
        Result := IsNull and TMemData(Data).GetNull(FieldNo, RecBuf)
      else
        Result := TMemData(Data).CompareFieldValue(Buffer, BufferType, Data.Fields[FieldNo - 1], RecBuf, []) = 0;
    end;
end;